Environmental preparation
-
Create database tables user, account, role, and user_role
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL auto_increment, `username` varchar(32) NOT NULL COMMENT '用户名称', `birthday` datetime default NULL COMMENT '生日', `sex` char(1) default NULL COMMENT '性别', `address` varchar(256) default NULL COMMENT '地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');
DROP TABLE IF EXISTS `account`; CREATE TABLE `account` ( `ID` int(11) NOT NULL COMMENT '编号', `UID` int(11) default NULL COMMENT '用户编号', `MONEY` double default NULL COMMENT '金额', PRIMARY KEY (`ID`), KEY `FK_Reference_8` (`UID`), CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `users` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `account`(`ID`,`UID`,`MONEY`) values (1,57,1000),(2,56,1000),(3,57,2000);
DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `ID` int(11) NOT NULL COMMENT '编号', `ROLE_NAME` varchar(30) default NULL COMMENT '角色名称', `ROLE_DESC` varchar(60) default NULL COMMENT '角色描述', PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');
DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `UID` int(11) NOT NULL COMMENT '用户编号', `RID` int(11) NOT NULL COMMENT '角色编号', PRIMARY KEY (`UID`,`RID`), KEY `FK_Reference_10` (`RID`), CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`), CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);
-
Create entity classes User, Account and Role under the domain layer
package com.chenpeng.domain; import java.io.Serializable; import java.util.Date; import java.util.List; public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; //一对多关系映射,主表实体应该包含从表实体的集合应用 private List<Account> accounts; public List<Account> getAccounts() { return accounts; } public void setAccounts(List<Account> accounts) { this.accounts = accounts; } //多对多关系映射 private List<Role> roles; public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", birthday=" + birthday + ", sex='" + sex + '\'' + ", address='" + address + '\'' + '}'; } }
package com.chenpeng.domain; import java.io.Serializable; public class Account implements Serializable { private Integer id; private Integer uid; private Double money; //多对一关系映射,从表实体应该包含主表实体的引用 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", uid=" + uid + ", money=" + money + '}'; } }
package com.chenpeng.domain; import java.io.Serializable; import java.util.List; public class Role implements Serializable { private Integer id; private String roleName; private String roleDesc; //多对多关系映射 private List<User> users; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleDesc() { return roleDesc; } public void setRoleDesc(String roleDesc) { this.roleDesc = roleDesc; } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } @Override public String toString() { return "Role{" + "id=" + id + ", roleName='" + roleName + '\'' + ", roleDesc='" + roleDesc + '\'' + '}'; } }
-
Create the main configuration file SqlMapConfig.xml in the resources directory
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入Mybatis的xml约束 --> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--Mybatis的主配置文件--> <configuration> <!--配置properties--> <properties url="file:///C:/Users/chenpeng/IdeaProjects/Mybatis/src/main/resources/jdbcConfig.properties"> </properties> <!--使用typeAliases配置别名,它只能配置domain中类的别名--> <typeAliases> <package name="com.chenpeng.domain"/> </typeAliases> <!--配置环境--> <environments default="mysql"> <!--配置mysql的环境--> <environment id="mysql"> <!--配置事务的类型--> <transactionManager type="JDBC"></transactionManager> <!--配置数据源(连接池)--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <package name="com.chenpeng.dao"/> </mappers> </configuration>
Multi-table query
Many-to-one query
Implement many-to-one query
-
Define the query method in the AccountDao interface of the dao layer
public interface AccountDao { /** * 查询所有账户同时包含对应的用户信息 * @return */ List<Account> findAll(); }
-
Add configuration in AccountDao.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="com.chenpeng.dao.AccountDao"> <resultMap id="accountUserMap" type="account"> <id property="id" column="aid"></id> <result property="uid" column="uid"></result> <result property="money" column="money"></result> <!--多对一的关系映射,配置封装user的内容--> <association property="user" column="uid" javaType="user"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> </association> </resultMap> <!--查询所有账户同时包含对应的用户信息--> <select id="findAll" resultMap="accountUserMap"> select u.*,a.id as aid,a.uid,a.money from users u,account a where u.id = a.uid </select> </mapper>
One-to-many query
Implement one-to-many query
-
Define the query method in the UserDao interface of the dao layer
public interface UserDao { /** * 查询所有用户同时包含对应的账户信息 * @return */ List<User> findAll(); }
-
Add configuration in UserDao.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="com.chenpeng.dao.UserDao"> <resultMap id="userAccountMap" type="user"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> <!--配置user对象中accounts集合的映射--> <collection property="accounts" ofType="account"> <id property="id" column="aid"></id> <result property="uid" column="uid"></result> <result property="money" column="money"></result> </collection> </resultMap> <!--查询所有用户同时包含对应的账户信息--> <select id="findAll" resultMap="userAccountMap"> select u.*,a.id as aid,a.uid,a.money from users u left outer join account a on u.id = a.uid </select> </mapper>
Many-to-many query
Implement many-to-many queries
-
Query all users also contain the corresponding role information
-
Define the query method in the UserDao interface of the dao layer
public interface UserDao { /** * 查询所有用户同时包含对应的角色信息 * @return */ List<User> findAll(); }
-
Add configuration in UserDao.xml
<resultMap id="userMap" type="user"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> <!--配置user对象中roles集合的映射--> <collection property="roles" ofType="role"> <id property="id" column="roleid"></id> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> </collection> </resultMap> <!--查询所有用户同时包含对应的角色信息--> <select id="findAll" resultMap="userMap"> select u.*,ur.*,r.id as roleid,r.role_name,role_desc from users u left outer join user_role ur on ur.uid = u.id left outer join role r on r.id = ur.rid </select>
-
-
The role used in the query also contains the corresponding user information
-
Define the query method in the dao layer interface RoleDao
public interface RoleDao { /** * 查询所有角色同时包含用户的信息 * @return */ List<Role> findAll(); }
-
Add configuration in RoleDao.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="com.chenpeng.dao.RoleDao"> <resultMap id="roleMap" type="role"> <id property="id" column="id"></id> <result property="roleName" column="role_name"></result> <result property="roleDesc" column="role_desc"></result> <collection property="users" ofType="user"> <id property="id" column="userid"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> </collection> </resultMap> <select id="findAll" resultMap="roleMap"> select r.*,ur.*,u.id as userid,u.username,u.birthday,u.sex,u.address from role r left outer join user_role ur on r.id = ur.rid left outer join users u on ur.uid = u.id </select> </mapper>
-
Lazy loading
What is lazy loading
- Only when the data is actually used, the query is initiated. What is not used is no query. It is loaded on demand, also called lazy loading.
- In multi-table queries, one-to-many and many-to-many usually use lazy loading
What is loading immediately
- Whether it is used or not, as soon as the method is called, the query is initiated immediately
- In multi-table queries, many-to-one and one-to-one usually use immediate loading
Implement lazy loading
Turn on Mybatis lazy loading
Add configuration in Mybatis main configuration file SqlMapConfig.xml
<!--配置mybatis延迟加载的全局开关-->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
Lazy loading of many-to-one queries
-
Dao layer interface method for defining main table query and attached table query
-
Define the query method findAll () in AccountDao
public interface AccountDao { /** * 查询所有账户 * @return */ List<Account> findAll(); }
-
Define the query method findById () in UserDao
public interface UserDao { /** * 根据id查询用户 * @param id * @return */ User findById(Integer id); }
-
-
Configure the above two query methods in the configuration file
-
Add configuration in AccountDao
<?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.chenpeng.dao.AccountDao"> <resultMap id="accountUserMap" type="account"> <id property="id" column="id"></id> <result property="uid" column="uid"></result> <result property="money" column="money"></result> <!--多对一的关系映射,配置封装user的内容--> <association property="user" column="uid" javaType="user" select="com.chenpeng.dao.UserDao.findById"> </association> </resultMap> <!--查询所有--> <select id="findAll" resultMap="accountUserMap"> select * from account </select> </mapper>
-
Add configuration in UserDao.xml
<select id="findById" parameterType="int" resultType="user"> select * from users where id = #{uid} </select>
-
One-to-many lazy loading
-
Dao layer interface method for defining main table query and attached table query
-
Define the query method in UserDao
public interface UserDao { /** * 查询所有用户 * @return */ List<User> findAll(); }
-
Define the query method in AccountDao
public interface AccountDao { /** * 根据用户id查询账户 * @return */ List<Account> findByUid(Integer uid); }
-
-
Configure the above two query methods in the configuration file
-
Add configuration in UserDao.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="com.chenpeng.dao.UserDao"> <resultMap id="userMap" type="user"> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="birthday" column="birthday"></result> <result property="sex" column="sex"></result> <result property="address" column="address"></result> <!--配置user对象中accounts集合的映射--> <collection property="accounts" ofType="account" column="id" select="com.chenpeng.dao.AccountDao.findByUid"> </collection> </resultMap> <!--查询所有--> <select id="findAll" resultMap="userMap"> select * from users </select> </mapper>
-
Add configuration in AccountDao
<!--根据用户id查询账户--> <select id="findByUid" resultType="account" parameterType="int"> select * from account where uid = #{uid} </select>
-
Cache in Mybatis
What is cache
- Refers to data temporarily stored in memory
What kind of data can use cache
- Query frequently, the data does not change frequently, and the accuracy of the data does not greatly affect the results
What kind of data can not use cache
- The data changes frequently, and the accuracy of the data has a great influence on the results
Level 1 cache in Mybatis
-
The first-level cache in Mybatis is the cache of the SqlSession object in Mybatis. When we execute the query, the results of the query will be stored in an area provided by SqLSession (the structure of the area is a map collection)
-
When we query the same data again, Mybatis will first go to the SqLSession to check if there is any, and if so, take it out directly
-
When the SqLSession object disappears, the first-level cache of Mybatis also disappears
-
Test first level cache
-
Define the test method in UserTest
@Test public void testFirstCache(){ User user = userDao.findById(41); System.out.println(user); User user1 = userDao.findById(41); System.out.println(user1); System.out.println(user == user1); }
-
The output is
com.chenpeng.domain.User@4bb4de6a com.chenpeng.domain.User@4bb4de6a true
The user object of the two queries is the same
-
-
Trigger to clear the first-level cache: When calling the SqlSession object's modify, add, delete, commit () and close () methods, it will clear the first-level cache
Second-level cache in Mybatis
- The secondary cache in Mybatis is the cache of the SqlSessionFactory object, and the SqlSession object created by the same SqlSessionFactory object shares its cache
Steps for using secondary cache
-
Let the Mybatis framework support secondary cache
Add configuration in the main configuration file SqlMapConfig.xml
<settings> <setting name="cacheEnabled" value="true"/> </settings>
-
Make the current mapping file support second-level cache
Add configuration in UserDao.xml
<!--开启user支持二级缓存--> <cache></cache>
-
Let the current query method support secondary cache
In
<select>
add taguseCache
attributes<select id="findById" parameterType="int" resultType="user" useCache="true"> select * from users where id = #{uid} </select>
-
Test the secondary cache
Define test method
@Test public void testSecondCache(){ SqlSession sqlSession1 = factory.openSession(); UserDao userDao1 = sqlSession1.getMapper(UserDao.class); User user1 = userDao1.findById(58); System.out.println(user1); SqlSession sqlSession2 = factory.openSession(); UserDao userDao2 = sqlSession2.getMapper(UserDao.class); User user2 = userDao2.findById(58); System.out.println(user2); System.out.println(user1); System.out.println(user1 == user2); }
The output is
com.chenpeng.domain.User@aecb35a com.chenpeng.domain.User@4bb4de6a false
The user object of the two queries is different. This is because the cache of the SqlSessionFactory object stores data instead of objects. During the second query, the SqlSessionFactory only encapsulates the cached data into the User, so the two are different.