Mybatis 中的延迟加载 问题:
在一对多中,当我们有一个用户,它有100个账户。在查询用户的时候,要不要把关联的账户查出来?在查询账户的时候,要不要把关联的用户查出来?
在查询用户时,用户下的账户信息应该是,什么时候使用,什么时候查询
在查询账户时,账户的所属用户信息应该是随着账户查询时一起查询出来的
在对应的四种表关系中:一对多,多对一,一对一,多对多
一对多,多对多(关联的对象是多):通常情况下我们都是采用延迟加载。
多对一,一对一(关联的对象是一):通常情况下我们都是采用立即加载
association、collection 具备延迟加载功能
使用 assocation 实现延迟加载
需求:
查询账户信息的同时查询用户信息(一对一)
账户的持久层 DAO 接口 src\main\java\com\conv\dao\IAccountDao.java
1 2 3 4 5 6 7 8 9 10 package com.conv.dao; public interface IAccountDao { /** * 查询所有账户,同时还要获取到当前账户的所属用户信息 * @return */ List<Account > findAll(); }
账户的持久层映射文件 src\main\resources\com\conv\dao\IAccountDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.conv.dao.IAccountDao" > <resultMap id ="accountUserMap" type ="account" > <id property ="id" column ="id" /> <result property ="uid" column ="uid" /> <result property ="money" column ="money" /> <association property ="user" column ="uid" javaType ="user" select ="com.conv.dao.IUserDao.findById" /> </resultMap > <select id ="findAll" resultMap ="accountUserMap" > select * from account </select > </mapper >
用户的持久层接口 src\main\java\com\conv\dao\IUserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.conv.dao;public interface IUserDao { List<User> findAll () ; User findById (Integer userId) ; }
用户的持久层映射文件 src\main\resources\com\conv\dao\IUserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.conv.dao.IUserDao" > <select id ="findAll" resultType ="com.conv.domain.User" > select * from user u left outer join account a on u.id = a.uid </select > <select id ="findById" parameterType ="Int" resultType ="com.conv.domain.User" > select * from user where id = #{uid} </select > </mapper >
编写测试只查帐户信息不查用户信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.conv.test;public class AccountTest { private InputStream in; private SqlSession session; IAccountDao accountDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); accountDao = session.getMapper(IAccountDao.class); } @After public void destroy () throws IOException { session.commit(); session.close(); in.close(); } @Test public void testFindAll () { List<Account> accounts = accountDao.findAll(); } }
使用 Collection 实现延迟加载
同样我们也可以在一对多关系配置的 <collection>
结点中配置延迟加载策略。
<collection>
结点中也有 select 属性,column 属性。
需求:
完成加载用户对象时,查询该用户所拥有的账户信息。(一对多)
在 User 实体类中加入 List<Account>
属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package com.conv.domain;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; } 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 + '\'' + '}' ; } }
账户的持久层 DAO 接口 src\main\java\com\conv\dao\IAccountDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.conv.dao;public interface IAccountDao { List<Account> findAll () ; List<Account> findByUid (Integer uid) ; }
编写用户持久层映射配置 src\main\resources\com\conv\dao\IUserDao.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.conv.dao.IUserDao" > <resultMap id ="userMap" type ="user" > <id column ="id" property ="id" /> <result column ="username" property ="username" /> <result column ="address" property ="address" /> <result column ="sex" property ="sex" /> <result column ="birthday" property ="birthday" /> <collection property ="accounts" ofType ="account" select ="com.conv.dao.IAccountDao.findByUid" column ="id" /> </resultMap > <select id ="findAll" resultMap ="userMap" > select * from user </select > </mapper >
编写账户持久层映射配置 1 2 3 4 <select id ="findByUid" resultType ="account" parameterType ="int" > select * from account where uid = #{uid} </select >
测试只加载用户信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.conv.test;public class UserTest { private InputStream in; private SqlSession session; IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(IUserDao.class); } @After public void destroy () throws IOException { session.commit(); session.close(); in.close(); } @Test public void testFindAll () { List<User> users = userDao.findAll(); } }
Mybatis 中的缓存 使用缓存可以减少和数据库的交互次数,提高执行效率。
适用于缓存的:
经常查询并且不经常改变的数据
数据的正确与否对最终结果影响不大的数据
Mybatis 中缓存分为一级缓存,二级缓存。
一级缓存 它指的是 Mybatis 中 SqlSession
对象的缓存。
当我们执行查询之后,查询的结果会同时存入到 SqlSession
为我们提供一块区域中。
该区域的结构是一个Map。当我们再次查询同样的数据,Mybatis 会先去 Sqlsession
中查询是否有,有的话直接拿出来用。
一级缓存是 SqlSession
级别的缓存,只要 SqlSession
没有 flush
或 close
,它就存在。
分析:
一级缓存是 SqlSession
范围的缓存,当调用 SqlSession
的修改,添加,删除,commit()
,close()
等方法时,就会清空一级缓存。
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void testFirstCache () { User user1 = userDao.findById(41 ); System.out.println(user1); session.clearCache(); userDao = session.getMapper(IUserDao.class); User user2 = userDao.findById(41 ); System.out.println(user2); System.out.println(user1 == user2); }
二级缓存 它指的是 Mybatis 中 SqlSessionFactory
对象的缓存。由同一个 SqlSessionFactory
对象创建的 SqlSession
共享其缓存。
二级缓存的使用步骤:
让 Mybatis 框架支持二级缓存(在 SqlMapConfig.xml
中配置)
1 2 3 4 <settings > <setting name ="cacheEnabled" value ="true" /> </settings >
让当前的映射文件支持二级缓存(在 IUserDao.xml
中配置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.conv.dao.IUserDao" > <cache /> <select id ="findAll" resultType ="user" > select * from user </select > <select id ="findById" parameterType ="Int" resultType ="com.conv.domain.User" useCache ="true" > select * from user where id = #{uid} </select > <update id ="updateUser" parameterType ="user" > update user set username = #{username},address = #{address} where id = #{id} </update > </mapper >
让当前的操作支持二级缓存(在 select
标签中配置)
将 UserDao.xml
映射文件中的 <select>
标签中设置 useCache=”true”
代表当前这个 statement
要使用 二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false
,禁用二级缓存。
二级缓存测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.conv.test;public class SecondLevelCacheTest { private InputStream in; SqlSessionFactory factory; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); } @After public void destroy () throws IOException { in.close(); } @Test public void testSecondCache () { SqlSession sqlSession1 = factory.openSession(); IUserDao dao1 = sqlSession1.getMapper(IUserDao.class); User user1 = dao1.findById(41 ); System.out.println(user1); sqlSession1.close(); SqlSession sqlSession2 = factory.openSession(); IUserDao dao2 = sqlSession2.getMapper(IUserDao.class); User user2 = dao2.findById(41 ); System.out.println(user2); sqlSession2.close(); System.out.println(user1 == user2); } }
经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二 次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。
值得注意的是,最终输出的结果是 false
,这是因为在二级缓存中寸的并不是对象,而是一些散装数据,每次查询就用这些数据封装一个对象返回,所以两个对象是不同的。
Mybatis 中的注解开发 Mybatis 使用注解开发的方式可以减少编写 Mapper 映射文件。
mybatis 的常用注解说明
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与 @Result 一起使用,封装多个结果集
@ResultMap:实现引用 @Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider:实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
使用 Mybatis 注解实现单表 CRUD 单表的 CRUD 操作是最基本的操作,前面我们的学习都是基于 Mybaits 的映射文件来实现的
编写实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.conv.domain;public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; 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 + '\'' + '}' ; } }
使用注解方式开发持久层接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.conv.dao;public interface IUserDao { @Select("select * from user") List<User> findAll () ; @Insert("insert into user(username, address, sex, birthday)" + " values(#{username}, #{address}, #{sex}, #{birthday})") void saveUser (User user) ; @Update("update user set username=#{username},sex=#{sex},address=#{address},birthday=#{birthday} " + "where id = #{id}") void updateUser (User user) ; @Delete("delete from user where id = #{id}") void deleteUser (Integer userId) ; @Select("select * from user where id = #{id}") User findById (Integer userId) ; @Select("select * from user where username like #{username}") List<User> findUserByName (String userName) ; @Select("select count(id) from user") int findTotal () ; }
通过注解方式,我们就不需要再去编写 UserDao.xml 映射文件了。
编写 SqlMapConfig 配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <?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 resource ="jdbcConfig.properties" /> <typeAliases > <package name ="com.conv.domain" /> </typeAliases > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <package name ="com.conv.dao" /> </mappers > </configuration >
编写测试方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 package com.conv.test;public class MybatisAnnoTest { private InputStream in; private SqlSession session; SqlSessionFactory factory; IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(IUserDao.class); } @After public void destroy () throws IOException { session.commit(); session.close(); in.close(); } @Test @Ignore public void testFindAll () { List<User> users = userDao.findAll(); users.forEach(System.out::println); } @Test @Ignore public void testSaveUser () { User user = new User(); user.setUsername("mybatis annotation" ); user.setAddress("北京市昌平区" ); userDao.saveUser(user); } @Test @Ignore public void testUpdateUser () { User user = new User(); user.setUsername("mybatis annotation" ); user.setAddress("北京市昌平区" ); user.setId(86 ); user.setSex("女" ); user.setBirthday(new Date()); userDao.updateUser(user); } @Test @Ignore public void testDeleteUser () { userDao.deleteUser(87 ); } @Test @Ignore public void testFindOneUser () { User user = userDao.findById(41 ); System.out.println(user); } @Test @Ignore public void testFindByName () { List<User> users = userDao.findUserByName("%王%" ); users.forEach(System.out::println); } @Test public void testFindTotal () { System.out.println(userDao.findTotal()); } }
使用注解实现复杂关系映射(多表)开发及延迟加载 实现复杂关系映射之前我们可以在映射文件中通过配置 <resultMap>
来实现,在使用注解开发时我们需要借助@Results 注解,@Result 注解,@One 注解,@Many 注解。
复杂关系映射的注解说明 @Results 注解
代替的是标签 <resultMap>
该注解中可以使用单个 @Result
注解,也可以使用 @Result
集合 @Results({@Result(),@Result()})
或 @Results(@Result())
@Result 注解
代替了 <id>
标签和 <result>
标签
@Result 中 属性介绍:
property:需要装配的属性名
one:需要使用的 @One
注解(@Result(one = @One)()))
many:需要使用的 @Many
注解(@Result(many = @many)()))
@One 注解(一对一)
代替了 <assocation>
标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍:
select
指定用来多表查询的 sqlmapper
(全限定方法名)
fetchType
会覆盖全局的配置参数 lazyLoadingEnabled
(配置延迟加载或立即加载)
使用格式:
@Result(column = " ", property = "", one = @One(select=""))
@Many 注解(多对一)
代替了 <Collection>
标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
注意:聚集元素用来处理 ”一对多” 的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
(一般为 ArrayList
)但是注解中可以不定义;
使用格式:
@Result(property = "", column = "", many = @Many(select=""))
需求: 一个用户具有多个账户信息,所以形成了用户(User)与账户(Account)之间的一对多关系。
一对一关系映射:
加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载。(注解方式实现)
一对多关系映射:
查询用户信息时,也要查询他的账户列表。使用注解方式实现
Account 实体类加入 User 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package com.conv.domain;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 + '}' ; } }
User 实体类加入 List<Account>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package com.conv.domain;public class User implements Serializable { private Integer userId; private String userName; private Date userBirthday; private String userSex; private String userAddress; private List<Account> accounts; public List<Account> getAccounts () { return accounts; } public void setAccounts (List<Account> accounts) { this .accounts = accounts; } public Integer getUserId () { return userId; } public void setUserId (Integer userId) { this .userId = userId; } public String getUserName () { return userName; } public void setUserName (String userName) { this .userName = userName; } public Date getUserBirthday () { return userBirthday; } public void setUserBirthday (Date userBirthday) { this .userBirthday = userBirthday; } public String getUserSex () { return userSex; } public void setUserSex (String userSex) { this .userSex = userSex; } public String getUserAddress () { return userAddress; } public void setUserAddress (String userAddress) { this .userAddress = userAddress; } @Override public String toString () { return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", userBirthday=" + userBirthday + ", userSex='" + userSex + '\'' + ", userAddress='" + userAddress + '\'' + '}' ; } }
编写用户的持久层接口并使用注解配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package com.conv.dao;@CacheNamespace(blocking = true) public interface IUserDao { @Select("select * from user") @Results(id = "userMap", value = { @Result(id = true, column = "id", property = "userId"), @Result(column = "username", property = "userName"), @Result(column = "sex", property = "userSex"), @Result(column = "address", property = "userAddress"), @Result(column = "birthday", property = "userBirthday"), @Result(column = "id", property = "accounts", many = @Many(select = "com.conv.dao.IAccountDao.findAccountByUid", fetchType = FetchType.LAZY)) }) List<User> findAll () ; @Select("select * from user where id = #{id}") @ResultMap(value = {"userMap"}) User findById (Integer userId) ; @Select("select * from user where username like #{username}") @ResultMap(value = {"userMap"}) List<User> findUserByName (String userName) ; }
添加账户的持久层接口并使用注解配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.conv.dao;public interface IAccountDao { @Select("select * from account") @Results(id = "accountMap", value = { @Result(id = true, column = "id", property = "id"), @Result(column = "uid", property = "uid"), @Result(column = "money", property = "money"), @Result(property = "user", column = "uid", one = @One(select = "com.conv.dao.IUserDao.findById", fetchType = FetchType.EAGER)) }) List<Account> findAll () ; @Select("select * from account where uid = #{uid}") List<Account> findAccountByUid (Integer userId) ; }
测试一对一关联及延迟加载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.conv.test;public class AccountTest { private InputStream in; private SqlSession session; SqlSessionFactory factory; IAccountDao accountDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); accountDao = session.getMapper(IAccountDao.class); } @After public void destroy () throws IOException { session.commit(); session.close(); in.close(); } @Test public void testFindAll () { List<Account> accounts = accountDao.findAll(); } }
测试一对多关联 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.conv.test;@Ignore public class UserTest { private InputStream in; private SqlSession session; SqlSessionFactory factory; IUserDao userDao; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); userDao = session.getMapper(IUserDao.class); } @After public void destroy () throws IOException { session.commit(); session.close(); in.close(); } @Test public void testFindAll () { List<User> users = userDao.findAll(); users.forEach(user -> { System.out.println("----------每个用户的信息-------------" ); System.out.println(user); System.out.println("账户信息:" ); System.out.println(user.getAccounts()); }); } @Test public void testFindOneUser () { User user = userDao.findById(41 ); System.out.println(user); } @Test public void testFindByName () { List<User> users = userDao.findUserByName("%王%" ); users.forEach(System.out::println); } }
mybatis 基于注解的二级缓存 在 SqlMapConfig 中开启二级缓存支持 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <?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 resource ="jdbcConfig.properties" /> <settings > <setting name ="cacheEnabled" value ="true" /> </settings > <typeAliases > <package name ="com.conv.domain" /> </typeAliases > <environments default ="mysql" > <environment id ="mysql" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments > <mappers > <package name ="com.conv.dao" /> </mappers > </configuration >
在持久层接口中使用注解配置二级缓存 1 2 3 4 5 6 7 8 9 package com.conv.dao;@CacheNamespace(blocking = true) public interface IUserDao { }
测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.conv.test;public class SecondLevelCacheTest { private InputStream in; private SqlSessionFactory factory; @Before public void init () throws IOException { in = Resources.getResourceAsStream("SqlMapConfig.xml" ); factory = new SqlSessionFactoryBuilder().build(in); } @After public void destroy () throws IOException { in.close(); } @Test public void testFindOne () { SqlSession session = factory.openSession(); IUserDao userDao = session.getMapper(IUserDao.class); User user = userDao.findById(41 ); System.out.println(user); session.close(); SqlSession session1 = factory.openSession(); IUserDao userDao1 = session1.getMapper(IUserDao.class); User user1 = userDao1.findById(41 ); System.out.println(user1); session1.close(); } }
完结撒花~