MyBatis-Use resultMap to configure one-to-one and one-to-many relationships in detail

MyBatis-Use resultMap to map one-to-one and one-to-many problems in detail


1. Introduction to MyBaits

MyBatis is an excellent persistence layer framework, which encapsulates the process of operating the database of jdbc, so that developers only need to pay attention to the SQL itself, instead of spending energy to deal with such as registering the driver, creating a connection, creating a statement, manually setting parameters, Jdbc complicated process code such as result set retrieval. MyBatis configures various statements (statement, preparedStatemnt, CallableStatement) to be executed through xml or annotations, and maps the SQL in the statement to the java object to generate the final executed sql statement. Finally, the MyBatis framework executes the sql and returns the result Map it into a java object and return it.

Unlike other object-relational mapping frameworks, MyBatis does not associate Java objects with database tables, but instead associates Java methods with SQL statements. MyBatis allows users to take full advantage of the various functions of the database, such as stored procedures, views, various complex queries, and the proprietary features of a database. If you want to operate on legacy databases, non-standard databases, or have complete control over the execution of SQL, MyBatis is a good choice.

2. Summary of the issues that need to be paid attention to when creating the Mapper.xml file
  1. Create the header template of the Mapper.xml file
<?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="path"> </mapper>

fill in the path of the Mapper file

To create a new mapper, you need to first give it a namespace, which is equivalent to a separator, because we have many Mappers in the project, and each Mapper will define the corresponding addition, deletion, modification, and checking methods, in order to avoid method conflicts In order to facilitate management, each Mapper has its own namespace, and this namespace cannot be repeated.

  1. The location of xxxMapper.xml and xxxMapper.java

Note that in Maven, by default, Maven requires us to put XML configuration, properties configuration, etc., in the resources directory, if we force it in the java directory, by default, this configuration file will be automatically Ignore it. For these two problems, we have two solutions:

  • Don't ignore the XML configuration:
    We can add the following configuration in pom.xml to make Maven not ignore my
    XML configuration in the java directory :
<build>
	<resources>
	 <resource>
			<directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
    </resource>
        <resource>
            <directory>src/main/resources</directory>
		</resource>
	</resources>
</build>
  • According to the requirements of
    Maven, put the xml file in the resources directory according to the requirements of Maven. However, by default in MyBatis, xxxMapper.xml and xxxMapper interfaces must be put together. Therefore, we need to manually under the resources directory , Create a directory that is the same as the xxxMapper interface, so that we don’t need to add configuration to the pom.xml file, because this way of writing satisfies the requirements of both Maven and MyBatis.

  • **Note: When creating the same directory in resources, you cannot create multiple levels at a time, you can only create one level by level. Although it looks the same, it is actually different. If you create multiple levels at once, compile In the subsequent files, xxxMapper.xml and xxxMapper interfaces will not be put together... (I suffered a big loss before, every time I manually drag and drop the compiled file...)

  1. application.properties file configuration
//引入阿里巴巴的数据库连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
//设置驱动、端口号、数据库名、时区
spring.datasource.url=jdbc:mysql://localhost:3306/dataBaseName?serverTimezone=UTC

spring.datasource.username = root
spring.datasource.password = rootroot

server.port=8080
//日志级别 从小到大分别为 trace -> debug -> info -> warn -> error
logging.level.cn.stians.vblog.mapper=debug

3. MyBatis——resultMap mapping writing

  1. One-to-one relationship: For example, a book corresponds to one author, and the corresponding pojo is as follows:
public class Book {
    
    
 private Integer id; 
 private String name; 
 private Author author;//Book中装了一个作者
 	...
 	//省略get,set方法
 	...
 }
  • Query book by id
	Book getBookById(int id);
<?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="org.javaboy.mybatis.mapper.BookMapper">
<resultMap id="BookWithAuthor" type="org.javaboy.mybatis.model.Book">
	<id column="id" property="id"/>
	<result column="name" property="name"/>
	<!-- association 节点用来描述一对一关系-->
<association property="author" javaType="org.javaboy.mybatis.model.Author">
	<id column="aid" property="id"/>
	<result column="aname" property="name"/>
	<result column="aage" property="age"/> 
</association>
</resultMap>
 <select id="getBookById" resultMap="BookWithAuthor">
	SELECT b.*,a.`age` AS aage,a.`id` AS aid,a.`name` AS aname FRO
	M book b,author a WHERE b.`aid`=a.`id` AND b.`id`=#{id} 
</select>
</mapper>
  • Extracting the common attributes can reduce duplication of code
<?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="org.javaboy.mybatis.mapper.BookMapper">
	<resultMap id="BaseResultMap" type="org.javaboy.mybatis.model.Book">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
</resultMap>

<!-- extends 节点用来继承上面的BaseResultMap这个公共的模板,这样就可以不需要写公共的属性了-->
<resultMap id="BookWithAuthor" type="org.javaboy.mybatis.model.Bo ok" extends="BaseResultMap">
<association property="author" javaType="org.javaboy.mybatis.model.Author">
	<id column="aid" property="id"/>
	<result column="aname" property="name"/>
	<result column="aage" property="age"/> </association>
</resultMap>
<select id="getBookById" resultMap="BookWithAuthor">
	SELECT b.*,a.`age` AS aage,a.`id` AS aid,a.`name` AS aname FRO
	M book b,author a WHERE b.`aid`=a.`id` AND b.`id`=#{id}
</select>
</mapper>
  • Use lazy loading

The above loading method reads all the data at once. Then do the mapping in the resultMap. If the one-to-one attribute is not used very frequently, it may be used occasionally. In this case, we can also enable lazy loading. Lazy loading means to query the book first. In the process of querying the book, the author is not searched. When the user calls the author attribute in the book for the first time, the author is then searched.

  • Provide another method
Book getBookById(Integer id); 
Author getAuthorById(Integer id);
<resultMap id="BaseResultMap" type="org.javaboy.mybatis.model.Book"> 
	<id column="id" property="id"/>
	<result column="name" property="name"/>
</resultMap>
<resultMap id="BookWithAuthor2" type="org.javaboy.mybatis.model.Book" extends="BaseResultMap">
	<association property="author" javaType="org.javaboy.mybatis.model.Author" select="org.javaboy.mybatis.mapper.BookMapper.getAuthorById" column="aid" fetchType="lazy"/>
</resultMap>
<select id="getBookById2" resultMap="BookWithAuthor2">
	 select * from book where id = #{id}; 
</select>
<select id="getAuthorById" resultType="org.javaboy.mybatis.model.Author">
	select * from author where id = #{aid}; 
</select>

Here, when defining the association, you do not directly specify the mapped field, but specify the method to be executed, which is specified through the select field. Column represents the parameter field passed when the method is executed, and the last fetchType represents lazy loading.
Of course, to use lazy loading, you also need to enable it in the global configuration:

<settings>
	<setting name="lazyLoadingEnabled" value="true"/> 
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>
  1. One-to-many query For
    example, a user corresponds to multiple roles, the corresponding pojo class is as follows:
public class User {
    
    
	private Integer id; 
	private String username; 
	private String password; 
	private List<Role> roles;
	
	//省略get、set方法
	...
	}
  • Provide a method to query users based on id
	User getUserById(Integer id);
<resultMap id="UserWithRole" type="org.javaboy.mybatis.model.User"> <id column="id" property="id"/>
	<result column="username" property="username"/>
	<result column="password" property="password"/>
	<collection property="roles" ofType="org.javaboy.mybatis.model.Role">
		<id property="id" column="rid"/>
		<result property="name" column="rname"/> 
		<result property="nameZh" column="rnameZH"/>
	</collection>
</resultMap>
    
 <select id="getUserById" resultMap="UserWithRole">
	SELECT u.*,r.`id` AS rid,r.`name` AS rname,r.`nameZh` AS rnameZh
	FROM USER u,role r,user_role ur WHERE u.`id`=ur.`uid` AND ur.`rid`=r.`id` AND u.`id`=#{id}
</select>

In resultMap, the collection node is used to describe the mapping relationship of the collection. When mapping, it will automatically merge the data of one party, and then put the more party into the collection. This can be achieved by the id attribute.

  • This one-to-many can also be made into a form of lazy loading, then we first provide a role query method:
	User getUserById(Integer id);	
	List<Role> getRolesByUid(Integer id);

Then, in the XML file, handle lazy loading

<resultMap id="UserWithRole" type="org.javaboy.mybatis.model.User"> <id column="id" property="id"/>
	<result column="username" property="username"/>
	<result column="password" property="password"/>
	<collection property="roles" select="org.javaboy.mybatis.mapper.UserMapper.getRolesByUid" column="id" fetchType="lazy">
	</collection>
</resultMap>

<select id="getUserById" resultMap="UserWithRole"> 
	select * from user where id=#{id};
</select>

<!--这里也可以写到Role类对象的mapper.xml中去-->
<select id="getRolesByUid" resultType="org.javaboy.mybatis.model.Role">
	SELECT r.* FROM role r,user_role ur WHERE r.`id`=ur.`rid` AND ur.`uid`=#{id}
</select>

Guess you like

Origin blog.csdn.net/weixin_43941676/article/details/108563953
Recommended