mybatis - 1, grundlegende Einführung

1. Überblick über Mybatis

1.1 Warum brauchst du Mybatis?

Herkömmlicherweise hat die Verbindung zur Datenbank über jdbc viele Nachteile:
1. Jedes Mal, wenn Sie eine Verbindung laden, müssen Sie den Treibernamen explizit angeben.
2. Jedes Mal, wenn Sie eine Verbindung erhalten, müssen Sie die Verbindungsinformationen wie URL, Benutzer, Kennwort usw. angeben.
3. SQL-Anweisungen sind mit Java-Code gekoppelt Schwerwiegend
4. Der Parametertyp muss manuell beurteilt werden.
5. Das Ergebnis ist konzentriert und der Spaltenname und der Datentyp müssen von
Ihnen selbst beurteilt werden. 6. Jedes Mal, wenn Sie die Verbindung verwenden, müssen Sie manuell schließen

1.2 Was ist Mybatis?

Mybatis ist ein Semi-Orm-Persistenz-Framework, das auf dem JDBC-Paket basiert und SQL-Abfragen unterstützt. Solange die Verbindungsinformationen konfiguriert sind, müssen wir die Verbindung nicht selbst verwalten. Je nach Notwendigkeit, eine XML-Konfiguration oder eine Annotation zu verwenden, um eine SQL-Operation auszuführen. Ordnen Sie der Datenbank Schnittstellen und Pojo-Objekte zu.

1.3 Zwei Konzepte in mybatis

Mybatis bezeichnet das Entitätsklassenobjekt der Zuordnungsdatentabelle als Pojo-Objekt. Gleichzeitig muss eine Schnittstelle geschrieben werden. Die Schnittstelle definiert einige Methoden zum Betreiben der Tabelle. Mybatis betreibt die Tabellen in der Datenbank entsprechend der Zuordnungsbeziehung.

1.4 Die Architektur von Mybatis

mybatis - 1, grundlegende Einführung

Zweitens die Erstkonfiguration von mybatis

2.1 Pom-Abhängigkeiten einführen

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
</dependency>

2.2 Globale Konfigurationsdatei (mybatis-config.xml)

Diese Konfiguration definiert hauptsächlich die Arbeitsattribute von mybatis, z. B. Informationen zur Datenbankverbindung, z.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根标签 -->
<configuration>
<properties>
    <property name="driver" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/>
    <property name="username" value="root"/>
        <property name="password" value="123456"/>
   </properties>

   <!-- 环境,可以配置多个,default:指定采用哪个环境 -->
   <environments default="test">
      <!-- id:唯一标识 -->
      <environment id="test">
         <!-- 事务管理器,JDBC类型的事务管理器 -->
         <transactionManager type="JDBC" />
         <!-- 数据源,池类型的数据源 -->
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110" />
            <property name="username" value="root" />
            <property name="password" value="123456" />
         </dataSource>
      </environment>
      <environment id="development">
         <!-- 事务管理器,JDBC类型的事务管理器 -->
         <transactionManager type="JDBC" />
         <!-- 数据源,池类型的数据源 -->
         <dataSource type="POOLED">
            <property name="driver" value="${driver}" /> <!-- 配置了properties,所以可以直接引用 -->
            <property name="url" value="${url}" />
            <property name="username" value="${username}" />
            <property name="password" value="${password}" />
         </dataSource>
      </environment>
   </environments>
  </configuration>

Beispielvorlage:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根标签 -->
<configuration>
   <!-- 环境,可以配置多个,default:指定采用哪个环境 -->
   <environments default="test">
      <!-- id:唯一标识 -->
      <environment id="test">
         <!-- 事务管理器,JDBC类型的事务管理器 -->
         <transactionManager type="JDBC" />
         <!-- 数据源,池类型的数据源 -->
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdemo" />
            <property name="username" value="root" />
            <property name="password" value="123456" />
         </dataSource>
      </environment>
   </environments>
   <mappers>
     <mapper resource="mappers/MyMapper.xml" />  指定mapper配置文件目录
   </mappers>
</configuration>

2.3 Konfigurieren Sie Map.xml

Diese Datei wird verwendet, um SQL-Operationen zu konfigurieren, dh verwandte SQL-Operationen für Methoden in der Mapper-Schnittstelle zu binden. Wie zum Beispiel:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:根标签,namespace:命名空间,随便写,一般保证命名空间唯一 -->
<mapper namespace="MyMapper">
   <!-- statement,内容:sql语句。id:唯一标识,随便写,在同一个命名空间下保持唯一
      resultType:sql语句查询结果集的封装类型,tb_user即为数据库中的表
    -->
   <select id="selectUser" resultType="com.zpc.mybatis.User">
      select * from tb_user where id = #{id}
   </select>
</mapper>

Drei, die beiden von Mybatis verwendeten Methoden

Für die Verwendung von Mybatis gibt es zwei Möglichkeiten: eine ist die traditionelle und die andere die dynamische Proxy-Methode. Letzteres wird häufiger verwendet.
Schritte auf herkömmliche Weise:
1. Erstellen Sie eine UserDao-Schnittstelle, geben Sie die SQL-Operationsmethode an, die ausgeführt werden kann.
2. Implementieren Sie die UserDao-Schnittstelle.
3. Schreiben Sie die Konfigurationsdatei mapper.xml, die der UserDao-Schnittstelle entspricht. 4. Mapper, der der
sqlSession entspricht

Dynamische Proxy-Methode:
Im Vergleich zu den oben genannten Methoden können Sie den Schritt der Implementierung der UserDao-Schnittstelle direkt weglassen. Sie müssen nur die Schnittstelle definieren und die Konfigurationsdatei mapper.xml schreiben.

3.1 Vollständiges Beispiel für einen dynamischen Proxy

1. Erstellen Sie eine UserMapper-Oberfläche (entsprechend dem ursprünglichen UserDao).

public interface UserMapper {

   /**
    * 登录(直接使用注解指定传入参数名称)
    * @param userName
    * @param password
    * @return
    */
   public User login(@Param("userName") String userName, @Param("password") String password);

   /**
    * 根据表名查询用户信息(直接使用注解指定传入参数名称)
    * @param tableName
    * @return
    */
   public List<User> queryUserByTableName(@Param("tableName") String tableName);

   /**
    * 根据Id查询用户信息
    * @param id
    * @return
    */
   public User queryUserById(Long id);

   /**
    * 查询所有用户信息
    * @return
    */
   public List<User> queryUserAll();

   /**
    * 新增用户信息
    * @param user
    */
   public void insertUser(User user);

   /**
    * 根据id更新用户信息
    * @param user
    */
   public void updateUser(User user);

   /**
    * 根据id删除用户信息
    * @param id
    */
   public void deleteUserById(Long id);
}

2. Erstellen Sie UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:根标签,namespace:命名空间,随便写,一般保证命名空间唯一 ,为了使用接口动态代理,这里必须是接口的全路径名-->
<mapper namespace="com.zpc.mybatis.dao.UserMapper">
    <!--
       1.#{},预编译的方式preparedstatement,使用占位符替换,防止sql注入,一个参数的时候,任意参数名可以接收
       2.${},普通的Statement,字符串直接拼接,不可以防止sql注入,一个参数的时候,必须使用${value}接收参数
     -->
    <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
        select * from ${tableName}
    </select>

    <select id="login" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where user_name = #{userName} and password = #{password}
    </select>

    <!-- statement,内容:sql语句。
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       resultType:sql语句查询结果集的封装类型,使用动态代理之后和方法的返回类型一致;resultMap:二选一
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
     -->
    <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where id = #{id}
    </select>
    <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user
    </select>
    <!-- 新增的Statement
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
       useGeneratedKeys:开启主键回写
       keyColumn:指定数据库的主键
       keyProperty:主键对应的pojo属性名
     -->
    <insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
            parameterType="com.zpc.mybatis.pojo.User">
        INSERT INTO tb_user (
        id,
        user_name,
        password,
        name,
        age,
        sex,
        birthday,
        created,
        updated
        )
        VALUES
        (
        null,
        #{userName},
        #{password},
        #{name},
        #{age},
        #{sex},
        #{birthday},
        NOW(),
        NOW()
        );
    </insert>
    <!-- 
       更新的statement
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
     -->
    <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User">
        UPDATE tb_user
        <trim prefix="set" suffixOverrides=",">
            <if test="userName!=null">user_name = #{userName},</if>
            <if test="password!=null">password = #{password},</if>
            <if test="name!=null">name = #{name},</if>
            <if test="age!=null">age = #{age},</if>
            <if test="sex!=null">sex = #{sex},</if>
            <if test="birthday!=null">birthday = #{birthday},</if>
            updated = now(),
        </trim>
        WHERE
        (id = #{id});
    </update>
    <!-- 
       删除的statement
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
     -->
    <delete id="deleteUserById" parameterType="java.lang.String">
        delete from tb_user where id=#{id}
    </delete>
</mapper>

3. Die globale Konfigurationsdatei mybatis-config.xml führt UserMapper.xml ein

<mappers>
    <mapper resource="mappers/MyMapper.xml"/>
    <mapper resource="mappers/UserDaoMapper.xml"/>
    <mapper resource="mappers/UserMapper.xml"/>
</mappers>

4. Erstellen Sie UserMapper-Testfälle

import com.zpc.mybatis.dao.UserMapper;
import com.zpc.mybatis.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class UserMapperTest {

    public UserMapper userMapper;

    @Before
    public void setUp() throws Exception {
        // 指定配置文件
        String resource = "mybatis-config.xml";
        // 读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 构建sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        // 1. 映射文件的命名空间(namespace)必须是mapper接口的全路径
        // 2. 映射文件的statement的id必须和mapper接口的方法名保持一致
        // 3. Statement的resultType必须和mapper接口方法的返回类型一致
        // 4. statement的parameterType必须和mapper接口方法的参数类型一致(不一定)
        this.userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void testQueryUserByTableName() {
        List<User> userList = this.userMapper.queryUserByTableName("tb_user");
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void testLogin() {
        System.out.println(this.userMapper.login("hj", "123456"));
    }

    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
    }

    @Test
    public void testQueryUserAll() {
        List<User> userList = this.userMapper.queryUserAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void testInsertUser() {
        User user = new User();
        user.setAge(20);
        user.setBirthday(new Date());
        user.setName("大神");
        user.setPassword("123456");
        user.setSex(2);
        user.setUserName("bigGod222");
        this.userMapper.insertUser(user);
        System.out.println(user.getId());
    }

    @Test
    public void testUpdateUser() {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("静静");
        user.setPassword("123456");
        user.setSex(0);
        user.setUserName("Jinjin");
        user.setId("1");
        this.userMapper.updateUser(user);
    }

    @Test
    public void testDeleteUserById() {
        this.userMapper.deleteUserById("1");
    }
}

3.2 Schreiben der Mapper-Schnittstelle

Dies stellt hauptsächlich die Zuordnungsbeziehung zwischen SQL- und Schnittstellenmethoden bereit, die normalerweise wie folgt geschrieben wird:

public interface UserMapper {
    public void createUser(@Param(“参数ID”) 参数类型 参数名,。。。。。)
}

@Param(“参数ID”) 这个注释是用来给传入的参数指定一个id的,然后可以给mapper.xml中的sql语句通过 #{“参数ID”}进行引用,这样就可以获取到参数的值,每一个参数都得对应一个@Param注释

3.3 Probleme, die bei der dynamischen Proxy-Methode zu beachten sind

1. Der Namespace in der Mapper-Konfiguration muss mit dem vollständigen Pfad der
Mapper-Schnittstelle übereinstimmen. 2. Der Methodenname der Mapper-Schnittstelle muss mit der von SQL definierten ID übereinstimmen, z. B. der ID in der Auswahlnotiz.
3. Der Eingabeparametertyp der Methode der Mapper-Schnittstelle und der von SQL definierte Parametertyp Konsistent
4. Der Ausgabeparametertyp der Methode in der Mapper-Schnittstelle muss mit dem von SQL definierten Ergebnistyp übereinstimmen (manchmal resultMap, der später erläutert wird).

4. Detaillierte Erläuterung der Mapper-XML-Konfiguration (Hervorhebung)

Im dynamischen Proxy-Modus gibt es zwei wichtige Punkte zum Schreiben: Der eine ist die Vorbereitung der Mapper-Schnittstelle und der andere die Vorbereitung der Mapper-Konfigurationsdatei. Die Mapper-XML-Datei ist hauptsächlich die Vorbereitung der Quarknotiz (siehe Beispiel).

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:根标签,namespace:命名空间,随便写,一般保证命名空间唯一 ,为了使用接口动态代理,这里必须是接口的全路径名-->
<mapper namespace="com.zpc.mybatis.dao.UserMapper">
    <!--
       1.#{},预编译的方式preparedstatement,使用占位符替换,防止sql注入,一个参数的时候,任意参数名可以接收
       2.${},普通的Statement,字符串直接拼接,不可以防止sql注入,一个参数的时候,必须使用${value}接收参数
     -->
    <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
        select * from ${tableName}
    </select>

    <select id="login" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where user_name = #{userName} and password = #{password}
    </select>

    <!-- statement,内容:sql语句。
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       resultType:sql语句查询结果集的封装类型,使用动态代理之后和方法的返回类型一致;resultMap:二选一
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
     -->
    <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where id = #{id}
    </select>
    <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user
    </select>
    <!-- 新增的Statement
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
       useGeneratedKeys:开启主键回写
       keyColumn:指定数据库的主键
       keyProperty:主键对应的pojo属性名
     -->
    <insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
            parameterType="com.zpc.mybatis.pojo.User">
        INSERT INTO tb_user (
        id,
        user_name,
        password,
        name,
        age,
        sex,
        birthday,
        created,
        updated
        )
        VALUES
        (
        null,
        #{userName},
        #{password},
        #{name},
        #{age},
        #{sex},
        #{birthday},
        NOW(),
        NOW()
        );
    </insert>
    <!-- 
       更新的statement
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
     -->
    <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User">
        UPDATE tb_user
        <trim prefix="set" suffixOverrides=",">
            <if test="userName!=null">user_name = #{userName},</if>
            <if test="password!=null">password = #{password},</if>
            <if test="name!=null">name = #{name},</if>
            <if test="age!=null">age = #{age},</if>
            <if test="sex!=null">sex = #{sex},</if>
            <if test="birthday!=null">birthday = #{birthday},</if>
            updated = now(),
        </trim>
        WHERE
        (id = #{id});
    </update>
    <!-- 
       删除的statement
       id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
       parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
     -->
    <delete id="deleteUserById" parameterType="java.lang.String">
        delete from tb_user where id=#{id}
    </delete>
</mapper>

4.1 Verwendung von Rohnoten

4.1.1.select

select-Write
einige SQL-Anweisungen select Attributbeschreibungen:
id attribute: Die eindeutige Kennung der Anweisung im aktuellen Namespace. Muss. Die Methodennamen in den ID- und Mapper-Schnittstellen müssen identisch sein.
resultType: Ordnet die Ergebnismenge dem Objekttyp von Java zu. Erforderlich (wählen Sie einen aus resultMap aus)
parameterType: Der übergebene Parametertyp. Sie können
resultMap weglassen : Wenn die zurückgegebenen Daten keine einzelne Entitätszuordnungsklasse sind, z. B. eine gemeinsame Abfrage mit mehreren Tabellen, müssen Sie diese verwenden, wie später ausführlich beschrieben wird

4.1.2.insert

Die Beschreibung mehrerer Attribute von insert:
id: eindeutiger Bezeichner, beiläufig schreiben, im selben Namespace eindeutig halten, nach Verwendung des dynamischen Proxys muss er mit dem Methodennamen
parameterType übereinstimmen : Der Typ des Parameters, nach Verwendung des dynamischen Proxys ist der Parametertyp der Methode derselbe
useGeneratedKeys: Aktivieren Sie den Primärschlüssel-Rückschreibschlüssel.
Spalte: Geben Sie den Primärschlüssel der Datenbank an.
keyProperty: Das Namensschild für die Pojo-Eigenschaft, das dem Primärschlüssel
in der spezifischen SQL-Anweisung entspricht.

4.1.3.update

id-Attribut: Der eindeutige Bezeichner der Anweisung im aktuellen Namespace (erforderliches Attribut);
parameterType: Der übergebene Parametertyp, der weggelassen werden kann.
Innerhalb des Etiketts: spezifische SQL-Anweisung.

4.1.4.löschen

Beschreibung mehrerer Attribute von delete:
id attribute: Die eindeutige Kennung der Anweisung unter dem aktuellen Namespace (erforderliches Attribut);
parameterType: Der übergebene Parametertyp, der weggelassen werden kann.
Innerhalb des Etiketts: spezifische SQL-Anweisung.

4.2 Der Unterschied zwischen # {} und $ {}

/**
 * #号
 * @param username1
 * @return
 */
User queryUserListByName1(@Param("username1") String username1);

/**
 * $号
 * @param username2
 * @return
 */
User queryUserListByName2(@Param("username2") String username2);

<select id="queryUserListByName1" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user WHERE user_name=#{username1}
</select>

<select id="queryUserListByName2" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user WHERE user_name='${username2}'//手动加了引号
</select>

# {} Einfach ersetzen? , Entspricht PreparedStatement, bei dem Platzhalter zum Ersetzen von Parametern verwendet werden, kann die SQL-Injection verhindern.
$ {} Steht für die Verkettung von Zeichenfolgen, die der Anweisung in der SQL-Anweisung entspricht, und verwendet Zeichenfolgen zum Spleißen von SQL. $ Kann ein beliebiger Teil der SQL sein, der an die Anweisung übergeben wird, und kann die SQL-Injection nicht verhindern.

Um $ {} zum Abrufen der Parameterwertinformationen zu verwenden, müssen Sie $ {value}
# {} verwenden. Dies bedeutet nur einen Platzhalter und hat nichts mit dem Namen des Parameters zu tun. Wenn nur ein Parameter vorhanden ist, entspricht dieser automatisch.

4.3 Dynamisches SQL (muss hinzugefügt werden)

if-Anweisung
wählen Sie, wenn andernfalls
wo und setzen Sie
foreach

4.4 ResultMap komplexe gemeinsame Abfrage wichtige Attribute

Wie bereits in den ausgewählten Notizen erwähnt, müssen Sie resultType und resultMap angeben. Wenn Sie eine einzelne Tabelle abfragen, wird im Allgemeinen ein einzelnes Objekt zurückgegeben, z. B. die Benutzertabelle, und die Abfrage gibt die Benutzertabelle zurück. Wenn eine gemeinsame Abfrage für mehrere Tabellen ausgeführt wird, können die von mehreren Tabellen zurückgegebenen Daten nicht mit einer einzelnen Entitätsklasse zugeordnet werden. Derzeit können Sie resultType nicht zum Angeben der zugeordneten Entitätsklasse verwenden. Sie müssen resultMap zum Angeben verwenden. Das Folgende ist eine Fallbeschreibung

4.4.1 Beschreibung der Tabellenbeziehung

Die Geschäftsbeziehung ist in diesem Fall die Beziehung zwischen Benutzern, Bestellungen, Bestelldetails und Produktinformationen. Unter diesen
entspricht eine Bestellung einem Benutzer.
Eine Bestellung kann mehrere Bestelldetails enthalten.
Ein Bestelldetail enthält eine Produktinformation.

Wenn sie miteinander verbunden sind: Die
Bestellung und der Benutzer stehen in einer Eins-zu-Eins-Beziehung, und die
Bestell- und Bestelldetails stehen in einer Eins-
zu-Viele-Beziehung

Bedarfsbeschreibung:
Eins-zu-Eins-Abfrage: Abfragereihenfolge und Abfrage der Informationen des
Bestellers Eins-zu-Viele-Abfrage: Abfragereihenfolge und Abfrage der Informationen des
Bestellers und der Bestelldetails Einzelpersoneninformationen und Bestelldetails sowie Produktinformationen in den Bestelldetails

4.4.2 Eins-zu-eins-Abfrage

Erstellen Sie zunächst die Auftragstabelle:

sql:
CREATE TABLE tb_order (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) DEFAULT NULL,
order_number varchar(255) DEFAULT NULL,
create datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

实体类:
public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    private Date created;
    private Date updated;
}

1. Methode 1: Die Kernidee besteht darin, das Order-Objekt zu erweitern, um die Zuordnung
abzuschließen . Neue OrderUser-Entitätsklasse erbt Order:

public class OrderUser extends Order {
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private Integer sex;
    private Date birthday;
    private Date created;
    private Date updated;
}

OrderMapper-Schnittstelle:

public interface OrderMapper {
     OrderUser queryOrderUserByOrderNumber(@Param("number") String number);
}

OrderMapper konfigurieren:
Da die zurückgegebenen Daten mit dem geerbten OrderUser zugeordnet werden können, können Sie den Typ direkt mit resultType angeben.

 <mapper namespace="com.zpc.mybatis.dao.OrderMapper">
    <select id="queryOrderUserByOrderNumber" resultType="com.zpc.mybatis.pojo.OrderUser">
      select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
   </select>
</mapper>

Test:

@Test
public void queryOrderUserByOrderNumber() throws Exception {
    OrderUser orderUser = orderMapper.queryOrderUserByOrderNumber("201807010001");
    System.out.println(orderUser);
}

2. Methode 2: Objektorientiertes Denken, Benutzerobjekt zum Bestellobjekt hinzufügen. Diese Methode wird häufiger verwendet, da die Kopplung zwischen der Hauptklasse und der Unterklasse gering ist und keine Zuordnung durch Vererbung erforderlich ist,
um die User-Eigenschaft im Order-Objekt hinzuzufügen:

public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    private Date created;
    private Date updated;
    private User user;
}

Mapper-Schnittstelle:

/**
 * 根据订单号查询订单用户的信息
 * @param number
 * @return
 */
Order queryOrderWithUserByOrderNumber(@Param("number") String number);

Mapper-Konfiguration: Es
ist zu beachten, dass die von select zurückgegebenen Daten nicht direkt mit einer einzelnen Entitätsklasse zugeordnet werden können, sondern die beiden Klassen Order und User betreffen. Schauen Sie sich zuerst das Beispiel an

<resultMap id="OrderUserResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
     <id column="id" property="id"/>
     <!--association:完成子对象的映射-->
     <!--property:子对象在父对象中的属性名-->
     <!--javaType:子对象的java类型-->
     <!--autoMapping:完成子对象的自动映射,若开启驼峰,则按驼峰匹配-->
     <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
         <id column="user_id" property="id"/>
     </association>
 </resultMap>

 <select id="queryOrderWithUserByOrderNumber" resultMap="OrderUserResultMap">  这里就指定resultMap为上面定义的resultMap
   select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
</select>

Test:

@Test
public void queryOrderWithUserByOrderNumber() throws Exception {
    Order order = orderMapper.queryOrderWithUserByOrderNumber("201807010001");
    System.out.println(order.getUser());
}

4.4.3 Verwendung von resultMap-one-to-one zwischen Hauptklasse und Unterklasse (Zuordnung)

<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识,后面通过该id引用" type="映射的pojo对象,就是主映射类的全类名" autoMapping="true 是否根据数据库字段名和映射类的属性名称自动映射">
  <id column="数据库表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型,可以省略" property="映射pojo对象的主键属性,就是主映射类中对应的主键的字段名" />

  <!--一般来说,如果映射类中的字段名和数据库的字段名相同,一一对应的话,就会自动进行映射,不需要配置下面的result标签,因为一般会开启autoMapping-->
  <result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属性)"/>

  <!--
  association就是定义主对象和子对象的映射关系的
  property :指定子对象在主对象中的字段名,也就是属性名称
  javaType:子对象的类型,需要指定为全类名
   autoMapping:true|false 是否按照数据库字段名和映射类的属性名称自动映射
  --> 
  <association property="pojo的一个对象属性" javaType="pojo关联的pojo对象" >
    <!--
    column:指定与子对象进行关联查询的主对象的数据库表的字段,也就是主数据库表中是用哪个字段字段和子表进行关联查询的。比如说主表order用 user_id,子表User用的是id字段,那么这里指定的就应该为 user_id
    jdbcType:字段类型,一般可以省略,自动映射的,这里是数据库中的类型,比如CHAR
    property:指定子对象的主键属性名

   如果有多个关联字段,那么就有多个对应的id标签。
    -->
    <id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主键属性"/>
    <!--一般来说,如果映射类中的字段名和数据库的字段名相同,一一对应的话,就会自动进行映射,不需要配置下面的result标签,因为一般会开启autoMapping-->
    <result  column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
  </association>
</resultMap>

4.4.4 Eins-zu-viele-Abfrage

Eins-zu-viele-Abfrage: Abfragereihenfolge, Informationen zur Abfragereihenfolge und Details zur Abfragereihenfolge.
Bestellung Bestellung:

public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    private Date created;
    private Date updated;
    private User user;

    private List<OrderDetail> detailList;
}

Beachten Sie die obige Detailliste, da eine Bestellung mehreren Bestelldetails entspricht. Verwenden Sie daher hier die Liste, um mehrere OrderDetail zu speichern.

Bestelldetails OrderDetail-Klasse:

public class OrderDetail {
    private Integer id;
    private Integer orderId;
    private Double totalPrice;
    private Integer status;
}

Mapper-Schnittstelle:

/**
 * 根据订单号查询订单用户的信息及订单详情
 * @param number
 * @return
 */
Order queryOrderWithUserAndDetailByOrderNumber(@Param("number") String number);

Mapper-Konfiguration:

<resultMap id="OrderUserDetailResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
    <id column="id" property="id"/>
    <!--collection:定义子对象集合映射-->
    <!--association:完成子对象的映射-->
    <!--property:子对象在父对象中的属性名-->
    <!--javaType:子对象的java类型-->
    <!--autoMapping:完成子对象的自动映射,若开启驼峰,则按驼峰匹配-->
    <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
        <id column="user_id" property="id"/>
    </association>

    <!--
    collection便签:用来映射集合类的,主类中的detailList
     -->
    <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
        <id column="id" property="id"/>
    </collection>
</resultMap>

 <select id="queryOrderWithUserAndDetailByOrderNumber" resultMap="OrderUserDetailResultMap">
   select * from tb_order o
   left join tb_user u on o.user_id=u.id
   left join tb_orderdetail od on o.id=od.order_id
   where o.order_number = #{number}
</select>

Test:

@Test
public void queryOrderWithUserAndDetailByOrderNumber() throws Exception {
    Order order = orderMapper.queryOrderWithUserAndDetailByOrderNumber("201807010001");
    System.out.println(order.getUser());
    System.out.println(order.getDetailList());
}

4.4.5 resultMap-Nutzung eins zu viele der Hauptklasse und Unterklasse (Sammlung)

<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识,后面通过该id引用" type="映射的pojo对象,就是主映射类的全类名" autoMapping="true 是否根据数据库字段名和映射类的属性名称自动映射">
  <id column="数据库表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型,可以省略" property="映射pojo对象的主键属性,就是主映射类中对应的主键的字段名" />

  <!--一般来说,如果映射类中的字段名和数据库的字段名相同,一一对应的话,就会自动进行映射,不需要配置下面的result标签,因为一般会开启autoMapping-->
  <result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属性)"/>

  <!--
  association就是定义主对象和子对象的映射关系的一对一
  property :指定子对象在主对象中的字段名,也就是属性名称
  javaType:子对象的类型,需要指定为全类名
   autoMapping:true|false 是否按照数据库字段名和映射类的属性名称自动映射
  --> 
  <association property="pojo的一个对象属性" javaType="pojo关联的pojo对象" >
    <!--
    column:指定与子对象进行关联查询的主对象的数据库表的字段,也就是主数据库表中是用哪个字段字段和子表进行关联查询的。比如说主表order用 user_id,子表User用的是id字段,那么这里指定的就应该为 user_id
    jdbcType:字段类型,一般可以省略,自动映射的
    property:指定子对象的主键属性名
    -->
    <id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主键属性"/>
    <!--一般来说,如果映射类中的字段名和数据库的字段名相同,一一对应的话,就会自动进行映射,不需要配置下面的result标签,因为一般会开启autoMapping-->
    <result  column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
  </association>

  <!-- 
  当主类和子类是一对多的关系时,就需要用到collection标签,也就是集合标签
  property:主类中对于子类集合对象的属性名
  ofType:集合对象中子类的全类名
  javaType:集合本身的类型,是list还是其他,一般可以省略
   autoMapping:是否开启字段自动映射
   -->
  <collection property="pojo的集合属性" ofType="集合中的pojo对象" autoMapping="true">

    <!--关联字段
    column:主类对应的数据库表中的关联字段名
    jdbcType:字段数据类型
    property:子类中定义的关联属性名

    如果有多个关联字段,那么就有多个对应的id标签。
    -->
    <id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
    <!--定义除了关联字段之外的字段和子类属性的映射关联,开启automapping且名字一样可省略-->
    <result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" /> 
  </collection>
</resultMap>

Unter https://www.cnblogs.com/zhengguangaa/p/9055840.html finden Sie Informationen zur Situation mehrerer zugeordneter Felder

4.4.6 Viele-zu-Viele-Abfrage

Viele-zu-viele-Abfrage: Abfragen von Bestellungen, Abfragen von Bestellinformationen und Abfragen der einzelnen Artikeldaten in Bestelldetails.
Produktdetails und Produktinformationen:

商品详情
public class OrderDetail {
    private Integer id;
    private Integer orderId;
    private Double totalPrice;
    private Integer status;
    private int itemId;
    private Item item;
}

商品信息
public class Item {
    private Integer id;
    private String itemName;
    private Float itemPrice;
    private String itemDetail;
}

Mapper-Schnittstelle:

/**
 * 根据订单号查询订单用户的信息及订单详情及订单详情对应的商品信息
 * @param number
 * @return
 */
Order queryOrderWithUserAndDetailItemByOrderNumber(@Param("number") String number);

Mapper-Konfiguration:

<resultMap id="OrderUserDetailItemResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
    <id column="id" property="id"/>
    <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
        <id column="user_id" property="id"/>
    </association>
    <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">

        <id column="detail_id" property="id"/>
        <!--这里就是集合中每个商品详情都对应一个商品信息,用法和上面的一样-->
        <association property="item" javaType="com.zpc.mybatis.pojo.Item" autoMapping="true">
            <id column="item_id" property="id"/>
        </association>
    </collection>
</resultMap>

 <select id="queryOrderWithUserAndDetailItemByOrderNumber" resultMap="OrderUserDetailItemResultMap">
   select * ,od.id as detail_id from tb_order o
   left join tb_user u on o.user_id=u.id
   left join tb_orderdetail od on o.id=od.order_id
   left join tb_item i on od.item_id=i.id
   where o.order_number = #{number}
</select>

Test:

@Test
public void queryOrderWithUserAndDetailItemByOrderNumber() throws Exception {
    Order order = orderMapper.queryOrderWithUserAndDetailItemByOrderNumber("201807010001");
    System.out.println(order);
    System.out.println(order.getUser());
    System.out.println(order.getDetailList());
}

Fünftens Springboot Integration Mybatis

Siehe http://blog.didispace.com/spring-boot-learning-21-3-6/

5.1 Pom-Abhängigkeiten hinzufügen

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>

这里的驱动按需要引入,这里以mysql为例
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

Hinweis zur Version von mybatis-spring-boot-Starter:

Version 2.1.x ist geeignet für: MyBatis 3.5+, Java 8+, Spring Boot 2.1+
2.0.x Version geeignet für: MyBatis 3.5+, Java
8+, Spring Boot 2.0 / 2.1 1.3.x Version geeignet für: MyBatis 3.4+, Java 6+, Spring Boot 1.5

5.2 Fügen Sie MySQL-Verbindungsinformationen hinzu

Fügen Sie MySQL-Verbindungsinformationen in application.properties hinzu

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=xxxxx
spring.datasource.password=xxxxx
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

5.3 Erstellen Sie eine Zieltabelle in MySQL

Beispiel: Benutzertabelle, die die Felder ID (BIGINT), Alter (INT) und Name (VARCHAR) enthält. Die spezifischen Erstellungsbefehle lauten wie folgt:

CREATE TABLE `User` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

5.4 Tabellenzuordnungsklasse erstellen

Zum Beispiel die Benutzerklasse:

@Data
@NoArgsConstructor
public class User {

    private Long id;

    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

5.5 Mapper-Schnittstelle erstellen

Beispiel: UserMapper:

public interface UserMapper {

    User findByName(@Param("name") String name);

    int insert(@Param("name") String name, @Param("age") Integer age);

}

5.6 Mapper-Konfiguration

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.didispace.chapter36.mapper.UserMapper">
    <select id="findByName" resultType="com.didispace.chapter36.entity.User">
        SELECT * FROM USER WHERE NAME = #{name}
    </select>

    <insert id="insert">
        INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})
    </insert>
</mapper>

5.6 Fügen Sie das Mapper-Schnittstellenpaket zum Scan-Speicherort hinzu

Fügen Sie die Konfiguration des Mapper-Scan-Pakets in der Hauptanwendungsklasse hinzu:

//使用这个注释即可,指定全包名
@MapperScan("com.didispace.chapter36.mapper")
@SpringBootApplication
public class Chapter36Application {

    public static void main(String[] args) {
        SpringApplication.run(Chapter36Application.class, args);
    }

}

5.7 Fügen Sie den Pfad der Mapper-Konfigurationsdatei in der Springboot-Konfiguration hinzu

Fügen Sie in application.properties Folgendes hinzu:

mybatis.mapper-locations=classpath:mapper/*.xml

classpath表示主类resources相对路径,上面表示resources下的mapper目录下的所有xml文件

5.8 Verwenden der Mapper-Schnittstelle zum Betreiben der Datenbank

Test:

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class Chapter36ApplicationTests {

    //直接使用springboot的自动装载配置
    @Autowired
    private UserMapper userMapper;

    @Test
    @Rollback
    public void test() throws Exception {
        userMapper.insert("AAA", 20);
        User u = userMapper.findByName("AAA");
        Assert.assertEquals(20, u.getAge().intValue());
    }

}

Ich denke du magst

Origin blog.51cto.com/kinglab/2486097
Empfohlen
Rangfolge