Umfassende Erklärung zu dynamischem SQL von MyBatis

Umfassende Erklärung zu dynamischem SQL von MyBatis

Vorwort

Bisher wurde MySQL über statisches SQL abgefragt. Wenn die Angelegenheit jedoch komplizierter ist, treten Probleme mit Anführungszeichen oder zusätzlichen Leerzeichen auf, wodurch der SQL-Code fehlerhaft wird. Um dieses Problem zu lösen, verwenden wir dynamisches SQL.

Die dynamische SQL-Technologie des Mybatis-Frameworks ist eine Funktion, die SQL-Anweisungen dynamisch unter bestimmten Bedingungen zusammenstellt. Ihr Zweck besteht darin, das Problem beim Zusammenfügen von SQL-Anweisungszeichenfolgen zu lösen. Dies geschieht über Tags.

Dynamisches SQL

1. Schauen Sie sich zuerst die Modulverzeichnisstruktur an

Erstellen Sie eine sql.xml-Datei im Mapper-Paket unter Ressourcen im Klassenpfad (Gemeinsamkeitsextraktion).

2. Physikalische Modellierung und logische Modellierung

Der Schritt der physischen Modellierung wird hier ausgelassen und die Datenbanktabelle muss der Pojo-Klasse entsprechen.

Paket Pojo;

importiere lombok.AllArgsConstructor;
importiere lombok.Data;
importiere lombok.NoArgsConstructor;

@Daten
@AllArgsKonstruktor
@NoArgsConstructor
öffentliche Klasse Mitarbeiter {
    private Integer empId;
    privater String empName;
    privates Doppeltes Angestelltengehalt;

}

3. Abhängigkeiten einführen

Kopieren Sie das vorherige log4j in die Classpath-Ressourcen. Darüber hinaus sieht die pom.xml-Datei nach der Einführung der Abhängigkeit wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<Projekt xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.beispiel</groupId>
    <artifactId>Tag03-mybatis02-dynamisch</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>Glas</packaging>

    <Abhängigkeiten>
        <Abhängigkeit>
            <groupId>org.projektlombok</groupId>
            <artifactId>Lombok</artifactId>
            <version>1.18.8</version>
            <scope>bereitgestellt</scope>
        </Abhängigkeit>

        <!-- Mybatis-Kern -->
        <Abhängigkeit>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </Abhängigkeit>

        <!-- Junit-Test -->
        <Abhängigkeit>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>Test</scope>
        </Abhängigkeit>

        <!-- MySQL-Treiber -->
        <Abhängigkeit>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.3</version>
            <scope>Laufzeit</scope>
        </Abhängigkeit>

        <!-- log4j-Protokoll -->
        <Abhängigkeit>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </Abhängigkeit>
    </Abhängigkeiten>

</Projekt>

4. Globale Konfigurationsdatei

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE Konfiguration
        ÖFFENTLICH "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<Konfiguration>
    <!--CamelCase-Zuordnung-->
    <Einstellungen>
        <Einstellungsname="mapUnderscoreToCamelCase" Wert="true"/>
    </Einstellungen>
    <!--Typaliaszuordnung-->
    <TypAliase>
        <Paketname="pojo"/>
    </TypAliases>
    <!--Umgebungskonfiguration-->
    <Umgebungen default="dev">
        <Umgebungs-ID="dev">
            <TransaktionsManager Typ="JDBC"></TransaktionsManager>
            <Datenquellentyp="POOLED">
                <Eigenschaftsname="Benutzername" Wert="root"/>
                <Eigenschaftsname="Passwort" Wert="888888"/>
                <Eigenschaftsname="URL" Wert="jdbc:mysql://localhost:3306/mybatis-Beispiel"/>
                <Eigenschaftsname="Treiber" Wert="com.mysql.jdbc.Driver"/>
            </dataSource>
                
        </Umgebung>
    </Umgebungen>
    <!--Pfadzuordnung-->
    <Mapper>
        <mapper-Ressource="mapper/sql.xml"/>
        <Paketname="Mapper"/>
    </Mapper>
</Konfiguration>

Hinweis: Es gibt CamelCase-Zuordnungen, Alias-Zuordnungen, Pfadzuordnungen und Pfadzuordnungen. Der Unterschied zum vorherigen besteht darin, dass wir hier eine Gemeinsamkeitsextraktion von SQL-Anweisungen durchgeführt haben und daher eine SQL-Pfadzuordnung <mapper resource="mapper/sql.xml"/> hinzufügen müssen.

5. Allgemeine SQL-Extraktionsdateien

Erstellen Sie eine sql.xml im Paket-Mapper unter den Klassenpfadressourcen (da unser SQL in die Mapping-Datei geschrieben werden soll und es sich auch um eine Mapping-Datei handelt, muss es unter Mapper geschrieben werden). Wenn Sie es verwenden müssen, fügen Sie <include refid="mapper.sql.mySelectSql"></include> dort hinzu, wo Sie diese SQL-Anweisung in der Mapping-Pfaddatei verwenden müssen.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE-Mapper
        ÖFFENTLICH "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.sql">

        <sql id="meinSelectSql">
    Wählen Sie emp_id, emp_name, emp_salary aus t_emp
</sql>


</mapper>

Die gemeinsame Extraktionsdatei kann auch unkonfiguriert bleiben. In diesem Fall können Sie die auszuführenden Anweisungen einfach in der Mapping-Datei neu schreiben.

6. Mapper-Schnittstelle

Insgesamt gibt es sieben Methoden

Paket-Mapper;

importiere org.apache.ibatis.annotations.Param;
importiere pojo.Employee;

importiere java.util.List;

öffentliche Schnittstelle EmployeeMapper {

     //Alle Mitarbeiter abfragen, deren empId größer ist als die empId des Mitarbeiters. Wenn empId null ist, alle Mitarbeiter abfragen List<Employee> selectEmployeeListByEmpId(Integer empId);

    /**
     * Abfrage der Gruppe von Mitarbeitern, deren empId größer ist als die in empId übergebene und deren Gehalt höher ist als das in empSalary übergebene. Wenn die in empId übergebene empId null ist, wird die empId-Bedingung nicht berücksichtigt. Wenn das in empSalary übergebene empSalary null ist, wird die empSalary-Bedingung nicht berücksichtigt. */
    Liste<Mitarbeiter> selectEmployeeListByEmpIdAndEmpSalary(@Param("empId") Integer empId, @Param("empSalary") Double empSalary);

    /**
     * Aktualisieren Sie Mitarbeiterinformationen basierend auf empId. Wenn ein Wert null ist, wird dieses Feld nicht aktualisiert. */
    void updateEmployee(Mitarbeiter Mitarbeiter);

    /**
     * Mitarbeiterinformationen basierend auf der Mitarbeiter-ID abfragen. Wenn 0<Mitarbeiter-ID<6, alle Mitarbeiter mit einer Mitarbeiter-ID größer als 6 abfragen. Wenn die Mitarbeiter-ID größer als 6 ist, alle Mitarbeiter mit einer Mitarbeiter-ID kleiner als 6 abfragen. * In allen anderen Fällen alle Mitarbeiterinformationen abfragen. */
    Liste<Mitarbeiter> selectEmployeeList(Integer empId);

    /**
     * Mitarbeiterinformationen hinzufügen */
    void insertEmployee(Mitarbeiter Mitarbeiter);

    /**
     * Mitarbeitersammlung stapelweise hinzufügen */
    void insertEmployeeList(@Param("employeeList") List<Mitarbeiter> Mitarbeiterliste);

    /**
     * Abfrage des Mitarbeitersatzes anhand des Mitarbeiter-ID-Satzes*/
    Liste<Mitarbeiter> selectEmployeeListByEmpIdList(Liste<Integer> idList);
}

Wenn

Ziel: Abfrage aller Mitarbeiter, deren empId größer als die empId des Mitarbeiters ist. Wenn empId null ist, Abfrage aller Mitarbeiter.

Die Methoden der Dao-Schnittstelle sind:
List<Employee> selectEmployeeListByEmpId(Integer empId);

Statisches SQL:

<select id="selectEmployeeListByEmpId" resultType="Mitarbeiter">

    <include refid="mapper.sql.mySelectSql"></include> wobei emp_id>#{empId}

</Auswählen>

Dynamisches SQL:

<select id="selectEmployeeListByEmpId" resultType="Mitarbeiter">
     <include refid="mapper.sql.mySelectSql"></include>
     <if test="empId != null">
         wobei emp_id>#{empId}
     </if>
 </Auswählen>

<include refid="mapper.sql.mySelectSql"></include> bedeutet, auf das extrahierte SQL-Fragment zu verweisen, oder Sie können die SQL-Anweisung direkt schreiben. Wenn es sich um statisches SQL handelt und die ID null ist, ist das Abfrageergebnis leer, aber dynamisches SQL kann alles finden. Das if-Tag enthält den Namen des Testattributs, der als Beurteilungsaussage dient.

Wo

Ziel:

  • Abfrage der Mitarbeitergruppe, deren empId größer als die übergebene empId und deren Gehalt größer als das übergebene empSalary ist
  • Wenn die übergebene empId null ist, wird die empId-Bedingung nicht berücksichtigt
  • Wenn das übergebene empSalary null ist, wird die Bedingung von empSalary nicht berücksichtigt.

Dao-Schnittstellenmethode:

List<Employee> selectEmployeeListByEmpIdAndEmpSalary(@Param("empId") Integer empId, @Param("empSalary") Double empSalary);

Dynamisches SQL mit if-Tag:

<select id="selectEmployeeListByEmpIdAndEmpSalary" resultType="Mitarbeiter">
    <include refid="mapper.sql.mySelectSql"></include> wobei
   <if test="empId != null">
            emp_id>#{empId}
        </if>
        <if test="empSalary != null">
           und emp_salary>#{empSalary}
        </if>

Hier können wir sehen, dass, wenn empSalary leer ist, die SQL-Anweisung select * from t_emp where emp_id >#{empId} lautet, aber wenn empId leer ist, lautet die SQL-Anweisung select * from t_emp where and emp_salary>#{empSalary}. Dies ist offensichtlich falsch und das if-Tag ist hier nicht anwendbar. Daher verwenden wir das Where-Tag oder das Trim-Tag.

Dynamisches SQL für „Wo und Wenn“:

<select id="selectEmployeeListByEmpIdAndEmpSalary" resultType="Mitarbeiter">
    <include refid="mapper.sql.mySelectSql"></include>
   
    <wo>
        <if test="empId != null">
            emp_id>#{empId}
        </if>
        <if test="empSalary != null">
           und emp_salary>#{empSalary}
        </if>
    </wo>
</Auswählen>

Die Rolle des Where-Tags:

  • Automatisches Hinzufügen des Schlüsselworts WHERE vor der ersten Bedingung
  • Den Konnektor vor der ersten Bedingung (UND, ODER usw.) automatisch entfernen

trimmen

Trimmen bedeutet aufbauen, was eigentlich bedeutet, Kopf und Schwanz zu entfernen. Hier folgen wir noch der obigen Methode.

Dynamisches SQL von trim

<select id="selectEmployeeListByEmpIdAndEmpSalary" resultType="Mitarbeiter">
    <include refid="mapper.sql.mySelectSql"></include>
    <trim prefix="WO" prefixOverrides="UND|ODER">
        <if test="empId != null">
            emp_id>#{empId}
        </if>

        <if test="empSalary != null">
            UND emp_salary>#{empSalary}
        </if>
    </trimmen>
</Auswählen>

Trimm-Tag:

  • Präfix: Gibt das Präfix an, das dynamisch hinzugefügt werden soll
  • Suffix-Attribut: Gibt das dynamisch hinzuzufügende Suffix an
  • prefixOverrides: Gibt das Präfix an, das dynamisch entfernt werden soll. Mehrere mögliche Werte werden durch „|“ getrennt.
  • Attribut „suffixOverrides“: Gibt das dynamisch zu entfernende Suffix an, wobei mehrere mögliche Werte durch „|“ getrennt werden.

Satz

Ziel: Mitarbeiterinformationen basierend auf empId aktualisieren. Wenn ein Wert null ist, aktualisieren Sie dieses Feld nicht.

Dao-Schnittstellenmethode:
void updateEmployee(Employee employee);
Verwenden wir das oben stehende Trim-Tag, um dieses Problem zu lösen.

Dynamisches SQL zum Trimmen:

<update id="updateMitarbeiter" >
    <trim-Präfix="set" PräfixOverrides=",">
        <if test="empName!=null">
            emp_name=#{empName}
        </if>
        <if test="empSalary!=null">
            , emp_salary=#{empSalary}
        </if>
    </trimmen>
    wobei emp_id=#{empId}
</Aktualisieren>

Dynamisches SQL des Satzes

<update id="updateMitarbeiter" >
    t_emp aktualisieren
     <Satz>
         <if test="empName!=null">
             emp_name=#{empName}
         </if>
         <if test="empSalary!=null">
            , emp_salary=#{empSalary}
         </if>
     </Satz>

Es ist zu sehen

Die Funktion des Set-Tags:

  • Fügt automatisch das Schlüsselwort SET vor dem ersten zu ändernden Feld hinzu
  • Entfernen Sie den Verbinder (,) vor dem ersten zu ändernden Feld.

wählen, wann, sonst

Ziel:

  • Mitarbeiterinformationen basierend auf der Mitarbeiter-ID abfragen. Wenn 0<emp_id<6, dann alle Mitarbeiter mit einer höheren Mitarbeiter-ID abfragen.
  • Wenn emp_id größer als 6 ist, dann frage alle Mitarbeiter mit weniger als emp_id ab
  • In anderen Fällen alle Mitarbeiterinformationen abfragen

Dao-Schnittstellenmethode:
List<Employee> selectEmployeeList(Integer empId);

Dynamisches SQL

<select id="selectEmployeeList" resultType="Mitarbeiter">
  
    <include refid="mapper.sql.mySelectSql"></include> wobei
    <wählen>
    <!--&lt; ist das Escape-Zeichen für < -->
        <wenn test="empId>0 und empId<6">
            emp_id>#{empId}
        </wann>
        <wenn test="empId>6">
            emp_id<#{empId}
        </wann>
        <sonst>
            1==1
        </sonst>
    </wählen>

</Auswählen>

wählen, wann, sonst
Äquivalent if ... else if... else if ... else

  • Wenn die Bedingung einer When-Anweisung erfüllt ist, werden die nachfolgenden When-Anweisungen nicht beurteilt.
  • Wenn alle „when“ nicht wahr sind, wird der Inhalt des „sonst“-Tags verkettet.

für jedes

Ziel 1: Mitarbeiterinformationen stapelweise hinzufügen

Dao-Schnittstellenmethode:

void insertEmployeeList(@Param("employeeList") List employeeList);

1. Dynamisches SQL

<insert id="insertEmployeeList">
    einfügen in t_emp(emp_name,emp_gehalt)Werte
    <!--Der Sammlungstag kann als Liste, Sammlung,
    Oder definieren Sie den Parameternamen selbst @Param("employeeList") List<Employee> employeeList-->
    <foreach-Sammlung="Mitarbeiterliste" Trennzeichen="," Element="Mitarbeiter">
        (#{emp.empName},#{emp.empGehalt})
    </foreach>
</einfügen>

Ziel 2: Abfragen mehrerer Mitarbeiterinformationen basierend auf mehreren IDs

Dao-Schnittstelle

List selectEmployeeListByEmpIdList(List idList);

2. Dynamisches SQL

<select id="selectEmployeeListByEmpIdList" resultType="Mitarbeiter">
    <include refid="mapper.sql.mySelectSql"></include>
     <foreach-Sammlung="Sammlung" item="id" separator=""," open="wo emp_id in (" close=")">
         #{Ausweis}
     </foreach>
</Auswählen>

Batchabfrage: foreach-Tag

  1. Sammlungsattribut: Gibt das zu durchlaufende Objekt an. Wenn der zu durchlaufende Parameter mit der Annotation @Param benannt ist, verwenden Sie diesen Namen. Wenn er nicht „Liste“ oder „Sammlung“ heißt.
  2. item-Attribut: stellt das durchsuchte Element dar. Wir werden dieses Element verwenden, um SQL-Anweisungen zusammenzustellen: Wenn das durchsuchte Element ein POJO-Objekt ist, erhalten wir die Daten über #{durchsuchtes Element.POJO-Attribut}; wenn das durchsuchte Element ein einfacher Datentyp ist, verwenden wir #{durchsuchtes Element}, um diesen einfachen Datentyp zu erhalten
  3. Trennzeichen-Attribut: Trennzeichen zwischen durchlaufenen Elementen
  4. offenes Attribut: Füge vor dem ersten durchlaufenen Element ein Präfix hinzu
  5. Attribut „close“: Fügt nach dem letzten durchlaufenen Element ein Suffix hinzu.

Testverfahren

Mapper importieren.EmployeeMapper;
importiere org.apache.ibatis.io.Resources;
importiere org.apache.ibatis.session.SqlSession;
importiere org.apache.ibatis.session.SqlSessionFactory;
importiere org.apache.ibatis.session.SqlSessionFactoryBuilder;
importiere org.junit.After;
importiere org.junit.Before;
importiere pojo.Employee;

importiere java.io.InputStream;
importiere java.util.ArrayList;
importiere java.util.List;

öffentliche Klasse Test {
    privater EmployeeMapper MitarbeiterMapper;
    privater InputStream ist;
    private SQLSession SQLSession;
    @Vor
    öffentliche void init() wirft Exception{
        // Ziel: Holen Sie sich das Proxy-Objekt der EmployeeMapper-Schnittstelle, rufen Sie damit die Methode selectEmployee(1) auf und geben Sie dann das Employee-Objekt zurück // 1. Konvertieren Sie die globale Konfigurationsdatei in einen Byte-Eingabestream = Resources.getResourceAsStream("mybatisConfig.xml");
        //2. Erstellen Sie ein SqlSessionFactoryBuilder-Objekt SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //3. Verwenden Sie das Builder-Muster, um ein SqlSessionFactory-Objekt zu erstellen SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        //4. Verwenden Sie den Factory-Modus, um ein SqlSession-Objekt zu erstellen sqlSession = sqlSessionFactory.openSession();
        //5. Verwenden Sie den dynamischen Proxy-Modus, um ein Proxy-Objekt der EmployeeMapper-Schnittstelle zu erstellen. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
    }


    @Nach
    öffentliche void after() wirft Exception{
        //Transaktion festschreiben!!!
        sqlSession.commit();
        //7. Ressourcen schließen is.close();
        sqlSession.close();
    }

    @org.junit.Test
    öffentliche void testSelectEmployeeListByEmpId(){
        System.out.println(employeeMapper.selectEmployeeListByEmpId(null));
    }

    @org.junit.Test
    öffentliche void testSelectEmployeeListByEmpIdAndEmpSalary(){
        System.out.println(employeeMapper.selectEmployeeListByEmpIdAndEmpSalary(2, 300d));
    }

    @org.junit.Test
    öffentliche void testUpdateEmployee(){
        Mitarbeiter Mitarbeiter = neuer Mitarbeiter(3,"celia", 9000d);

        employeeMapper.updateEmployee(Mitarbeiter);
    }

    @org.junit.Test
    öffentliche void testSelectEmployeeList(){
    System.out.println(employeeMapper.selectEmployeeList(7));
}

   @org.junit.Test
   öffentliche void testInsertEmployee(){
        employeeMapper.insertEmployee(neuer Mitarbeiter(null,"tom",300d));
    }

    @org.junit.Test
    öffentliche void testInsertEmployeeList(){
        Liste<Mitarbeiter> Mitarbeiterliste = neue ArrayList<>();
        für (int i = 11; i <= 20; i++) {
            employeeList.add(neuer Mitarbeiter(null,"aobama"+i,2000d));
        }

        employeeMapper.insertEmployeeList(employeeList);

    }

    @org.junit.Test
    öffentliche void testSelectEmployeeListByEmpIdList(){
        Liste<Integer> idList = neue ArrayList<>();
        idList.add(23);
        idList.add(33);
        idList.add(32);
        idList.add(21);
        idList.add(22);
        System.out.println(employeeMapper.selectEmployeeListByEmpIdList(idList));
    }


}

Dies ist das Ende dieses Artikels über MyBatis Dynamic SQL. Weitere verwandte Inhalte zu MyBatis Dynamic SQL finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • MyBatis löst das Problem des Kommas beim Aktualisieren dynamischer SQL
  • Mybatis dynamisches SQL, wenn Testschreiben und Regeln, detaillierte Erklärung
  • Zusammenfassung der Fallstricke beim Testen in Mybatis Dynamic SQL
  • Beispielcode für dynamischen SQL von Mybatis
  • Erste Schritte mit Mybatis-Entitätsklassennamen und dynamischem SQL mit mehreren Parametern in einer Stunde
  • Ein Artikel, der Ihnen das dynamische SQL von mybatis zeigt

<<:  Funktionsüberladung in TypeScript

>>:  So verwenden Sie das JQuery-Editor-Plugin tinyMCE

Artikel empfehlen

TD-Breitenproblem beim Zusammenführen von TD-Zellen

Im folgenden Beispiel ist die Anzeige normal, wenn...

Lösung für MySQL-Replikationsfehler aufgrund voller Festplatte

Inhaltsverzeichnis Fallbeispiel Lösung des Proble...

...

Detaillierte Zusammenfassung von MySQL und verbindungsbezogenen Timeouts

MySQL und verbindungsbezogene Timeouts Vorwort: H...

So implementieren Sie Lastenausgleich in MySQL

Vorwort MySQL ist ein schnelles, leistungsstarkes...

HTML-Codebeispiel: Detaillierte Erklärung von Hyperlinks

Hyperlinks sind die am häufigsten verwendeten HTM...

js kehrt zur vorherigen Seite zurück und aktualisiert den Code

1. Javascript kehrt zur vorherigen Seite zurück hi...

Ubuntu 15.04 öffnet den MySQL-Remote-Port 3306

Ubuntu 15.04 öffnet den MySQL-Remote-Port 3306. A...