MyBatis(四)
发布日期:2021-07-22 10:54:12 浏览次数:10 分类:技术文章

本文共 23320 字,大约阅读时间需要 77 分钟。

目录


JNDI

NDI:Java Naming and Directory Interface。是SUN公司推出的一套规范,属于JavaEE技术之一。目的是模仿windows系统中的注册表。

在服务器中注册数据源:

1.创建Maven的war工程并导入坐标

    
      
org.mybatis
      
mybatis
      
3.4.5
    
    
      
mysql
      
mysql-connector-java
      
5.1.6
    
    
      
log4j
      
log4j
      
1.2.12
    
    
      
junit
      
junit
      
4.10
    
  
    
javax.servlet
    
servlet-api
    
2.5
  
  
    
javax.servlet.jsp
    
jsp-api
    
2.0
  

2.在webapp文件下创建META-INF目录 

3.在META-INF目录中建立一个名为context.xml的配置文件

 

 

4.修改SqlMapConfig.xml中的配置


Mybatis中的延迟加载

什么是延迟加载——在真正使用数据时才发起查询,不用的时候不查询(按需查询(懒查询))
延迟加载
就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载
.
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快
坏处:
因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降
 
什么是立即加载——不管用不用,只要一调用方法,马上发起查询
在对应的四种表关系中:一对多,多对一,一对一,多对多
        一对多,多对多:通常情况下我们都是采用延迟加载
        多对一,一对一:通常情况下我们都是采用立即加载

使用 assocation 实现延迟加载

需求:
查询账户信息同时查询用户信息。
1
账户的持久层
DAO
接口
/**** 

Title: IAccountDao

*

Description: 账户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IAccountDao {/*** 查询所有账户,同时获取账户的所属用户名称以及它的地址信息* @return*/List
findAll();}
2
账户的持久层映射文件
select
填写我们要调用的
select
映射的
id
column
填写我们要传递给
select
映射的参数
3
用户的持久层接口和映射文件
/**** 

Title: IUserDao

*

Description: 用户的业务层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 根据 id 查询* @param userId* @return*/User findById(Integer userId);}
4
开启
Mybatis
的延迟加载策略
进入
Mybaits
的官方文档,找到
settings
的说明信息:
我们需要在
Mybatis
的配置文件
SqlMapConfig.xml
文件中添加延迟加载的配置。
5
编写测试只查账户信息不查用户信息。
/**** 

Title: MybastisCRUDTest

*

Description: 一对多账户的操作

*

Company: http://www.itheima.com/

*/public class AccountTest {private InputStream in ;private SqlSessionFactory factory;private SqlSession session;private IAccountDao accountDao;@Testpublic void testFindAll() {//6.执行操作List
accounts = accountDao.findAll();}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 SqlSession 对象session = factory.openSession();//5.创建 Dao 的代理对象accountDao = session.getMapper(IAccountDao.class);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{//7.释放资源session.close();in.close();}}
测试结果如下:
我们发现,因为本次只是将
Account
对象查询出来放入
List
集合中,并没有涉及到
User
对象,所以就没有 发出 SQL
语句查询账户所关联的
User
对象的查询。

使用 Collection 实现延迟加载

同样我们也可以在一对多关系配置的
<collection>
结点中配置延迟加载策略。
<collection>
结点中也有
select
属性,
column
属性。
需求:
完成加载用户对象时,查询该用户所拥有的账户信息。
1
User
实体类中加入
List<Account>
属性
/**** 

Title: User

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;private List
accounts;public List
getAccounts() {return accounts;}public void setAccounts(List
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;}@Overridepublic String toString() {return "User [id=" + id + ", username=" + username + ", birthday=" + birthday+ ", sex=" + sex + ", address="+ address + "]";}}
2
编写用户和账户持久层接口的方法
/*** 查询所有用户,同时获取出每个用户下的所有账户信息*/List
findAll();/*** 根据用户 id 查询账户信息* @param uid* @return*/List
findByUid(Integer uid);
3
编写用户持久层映射配置
<collection>
标签:
主要用于加载关联的集合对象
select
属性:
用于指定查询
account
列表的
sql
语句,所以填写的是该
sql
映射的
id
column
属性:
用于指定
select
属性的
sql
语句的参数来源,上面的参数来自于
user
id
列,所以就写成
id
这一 个字段名了
4
编写账户持久层映射配置
5
测试只加载用户信息
/**** 

Title: MybastisCRUDTest

*

Description: 一对多的操作

*

Company: http://www.itheima.com/

*/public class UserTest {private InputStream in ;private SqlSessionFactory factory;private SqlSession session;private IUserDao userDao;@Testpublic void testFindAll() {//6.执行操作List
users = userDao.findAll();}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 SqlSession 对象session = factory.openSession();//5.创建 Dao 的代理对象userDao = session.getMapper(IUserDao.class);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{session.commit();//7.释放资源session.close();in.close();}}
测试结果如下:
 

Mybatis中的缓存

——存在于内存中的临时数据

        使用缓存可以减少和数据库的交互次数,提高执行效率。
    什么样的数据能使用缓存,什么样的数据不能使用
        适用于缓存:
            经常查询并且不经常改变的。
            数据的正确与否对最终结果影响不大的
        不适用于缓存:
            经常改变的数据
            数据的正确与否对最终结果影响很大的

   Mybatis中的一级缓存和二级缓存

      一级缓存

           一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush close,它就存在。

            当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。
            该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了        

1
编写用户持久层
Dao
接口
/**** 

Title: IUserDao

*

Description: 用户的业务层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 根据 id 查询* @param userId* @return*/User findById(Integer userId);}
2
编写用户持久层映射文件
3
编写测试方法
/**** 

Title: MybastisCRUDTest

*

Description: 一对多的操作

*

Company: http://www.itheima.com/

*/public class UserTest {private InputStream in ;private SqlSessionFactory factory;private SqlSession session;private IUserDao userDao;@Testpublic void testFindById() {//6.执行操作User user = userDao.findById(41);System.out.println("第一次查询的用户:"+user);User user2 = userDao.findById(41);System.out.println("第二次查询用户:"+user2);System.out.println(user == user2);}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 SqlSession 对象session = factory.openSession();//5.创建 Dao 的代理对象userDao = session.getMapper(IUserDao.class);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{//7.释放资源session.close();in.close();}}
测试结果如下:
我们可以发现,虽然在上面的代码中我们查询了两次,但最后只执行了一次数据库操作,这就是
Mybatis
提供给我们的一级缓存在起作用了。因为一级缓存的存在,导致第二次查询 id
41
的记录时,并没有发出
sql
语句从数据库中查询数据,而是从一级缓存中查询
2.1一级缓存的分析
一级缓存是
SqlSession
范围的缓存,
当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存
第一次发起查询用户
id
1
的用户信息,先去找缓存中是否有
id
1
的用户信息,如果没有,从数据库查询用户信息得到用户信息,将用户信息存储到一级缓存中
如果
sqlSession
去执行
commit
操作(执行插入、更新、删除),清空
SqlSession
中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读
第二次发起查询用户
id
1
的用户信息,先去找缓存中是否有
id
1
的用户信息,缓存中有,直接从缓存中获取用户信息
2.2 
测试一级缓存的清空
/*** 测试一级缓存*/@Testpublic void testFirstLevelCache(){User user1 = userDao.findById(41);System.out.println(user1);// sqlSession.close();//再次获取 SqlSession 对象// sqlSession = factory.openSession();sqlSession.clearCache();//此方法也可以清空缓存userDao = sqlSession.getMapper(IUserDao.class);User user2 = userDao.findById(41);System.out.println(user2);System.out.println(user1 == user2);}/*** 测试缓存的同步*/@Testpublic void testClearlCache(){//1.根据 id 查询用户User user1 = userDao.findById(41);System.out.println(user1);//2.更新用户信息user1.setUsername("update user clear cache");user1.setAddress("北京市海淀区");userDao.updateUser(user1);//3.再次查询 id 为 41 的用户User user2 = userDao.findById(41);System.out.println(user2);System.out.println(user1 == user2);}
当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql 语句,从数据库进行了查询操作

      二级缓存

            它指的是Mybatis中SqlSessionFactory对象的缓存。二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

            二级缓存的使用步骤:
                第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
                第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
                第三步:让当前的操作支持二级缓存(在select标签中配置)

 
 
1
二级缓存结构图
首先开启
mybatis
的二级缓存。 sqlSession1 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。
如果
SqlSession3
去执行相同
mapper
映射下
sql
,执行
commit
提交,将会清空该
mapper
映射下的二级缓存区域的数据。
sqlSession2
去查询与
sqlSession1
相同的用户信息,首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。
2.二级缓存的开启与关闭
第一步:在
SqlMapConfig.xml
文件开启二级缓存
<
settings
>
因为
cacheEnabled
的取值默认就为
true
,所以这一步可以省略不配置。为
true
代表开启二级缓存;为false 代表不开启二级缓存。
第二步:配置相关的
Mapper
映射文件
<cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值
第三步:配置
statement
上面的
useCache
属性
UserDao.xml
映射文件中的
<select>
标签中设置
useCache=”true”
代表当前这个
statement
要使用二级缓存,如果不使用二级缓存可以设置为 false
注意:针对每次查询都需要最新的数据
sql
,要设置成
useCache=false
,禁用二级缓存。
3
二级缓存测试
/*** @author 黑马程序员* @Company http://www.ithiema.com*/public class SecondLevelCacheTest {private InputStream in;private SqlSessionFactory factory;@Before//用于在测试方法执行之前执行public void init()throws Exception{//1.读取配置文件,生成字节输入流in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.获取 SqlSessionFactoryfactory = new SqlSessionFactoryBuilder().build(in);}@After//用于在测试方法执行之后执行public void destroy()throws Exception{in.close();}/*** 测试一级缓存*/@Testpublic void testFirstLevelCache(){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
语句,所以此时的数据就只能是来自于我们所说的二级缓存。
4
二级缓存注意事项
当我们在使用二级缓存时,所缓存的类一定要实现
java.io.Serializable
接口,这种就可以使用序列化方式来保存对象
/**** 

Title: User

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;}

Mybatis中的注解开发

1 mybatis 的常用注解说明

@Insert:
实现新增
@Update:
实现更新
@Delete:
实现删除
@Select:
实现查询
@Result:
实现结果集封装
@Results:
可以与
@Result
一起使用,封装多个结果集
@ResultMap:
实现引用
@Results
定义的封装
@One:
实现一对一结果集封装
@Many:
实现一对多结果集封装
@SelectProvider:
实现动态
SQL
映射
@CacheNamespace:
实现注解二级缓存的使用

2 使用 Mybatis 注解实现基本 CRUD

单表的 CRUD
操作是最基本的操作,前面我们的学习都是基于
Mybaits
的映射文件来实现的。
1
编写实体类
/**** 

Title: User

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer userId;private String userName;private Date userBirthday;private String userSex;private String userAddress;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;}@Overridepublic String toString() {return "User [userId=" + userId + ", userName=" + userName + ", userBirthday="+ userBirthday + ", userSex="+ userSex + ", userAddress=" + userAddress + "]";}}
注意:
此处我们故意和数据库表的列名不一致。
2 使用注解方式开发持久层接口
/**** 

Title: IUserDao

*

Description: 用户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 查询所有用户* @return*/@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")})List
findAll();/*** 根据 id 查询一个用户* @param userId* @return*/@Select("select * from user where id = #{uid} ")@ResultMap("userMap")User findById(Integer userId);/*** 保存操作* @param user* @return*/@Insert("insert intouser(username,sex,birthday,address)values(#{username},#{sex},#{birthday},#{address})")@SelectKey(keyColumn="id",keyProperty="id",resultType=Integer.class,before =false, statement = { "select last_insert_id()" })int saveUser(User user);/*** 更新操作* @param user* @return*/@Update("update user setusername=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id} ")int updateUser(User user);/*** 删除用户* @param userId* @return*/@Delete("delete from user where id = #{uid} ")int deleteUser(Integer userId);/*** 查询使用聚合函数* @return*/@Select("select count(*) from user ")int findTotal();/*** 模糊查询* @param name* @return*/@Select("select * from user where username like #{username} ")List
findByName(String name);}

通过注解方式,我们就不需要再去编写 UserDao.xml 映射文件了 

3 编写 SqlMapConfig 配置文件

4
编写测试方法
/**** 

Title: MybatisAnnotationCRUDTest

*

Description: mybatis 的注解 crud 测试

*

Company: http://www.itheima.com/

*/public class MybatisAnnotationCRUDTest {/*** 测试查询所有*/@Testpublic void testFindAll() {List
users = userDao.findAll();for(User user : users) {System.out.println(user);}}/*** 测试查询一个*/@Testpublic void testFindById() {User user = userDao.findById(41);System.out.println(user);}/*** 测试保存*/@Testpublic void testSave() {User user = new User();user.setUserName("mybatis annotation");user.setUserSex("男");user.setUserAddress("北京市顺义区");user.setUserBirthday(new Date());int res = userDao.saveUser(user);System.out.println("影响数据库记录的行数:"+res);System.out.println("插入的主键值:"+user.getUserId());}/*** 测试更新*/@Testpublic void testUpdate() {User user = userDao.findById(63);user.setUserBirthday(new Date());user.setUserSex("女");int res = userDao.updateUser(user);System.out.println(res);}/*** 测试删除*/@Testpublic void testDelete() {int res = userDao.deleteUser(63);System.out.println(res);}/*** 测试查询使用聚合函数*/@Testpublic void testFindTotal() {int res = userDao.findTotal();System.out.println(res);}/*** 测试模糊查询*/@Testpublic void testFindByName() {List
users = userDao.findByName("%m%");for(User user : users) {System.out.println(user);}}private InputStream in;private SqlSessionFactory factory;private SqlSession session;private IUserDao userDao;@Before//junit 的注解public void init()throws Exception{//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建工厂SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(in);//3.创建 sessionsession = factory.openSession();//4.创建代理对象userDao = session.getMapper(IUserDao.class);}@After//junit 的注解public void destroy()throws Exception {//提交事务session.commit();//释放资源session.close();//关闭流in.close();}}

使用注解实现复杂关系映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,在使用注解开发时我们需要借 助@Results
注解,
@Result
注解,
@One
注解,
@Many
注解
1
复杂关系映射的注解说明
@Results
注解
代替的是标签
<resultMap>
该注解中可以使用单个
@Result
注解,也可以使用
@Result
集合
@Results
{@Result
(),
@Result
()
}
)或
@Results
@Result
())
@Resutl
注解
代替了
<id>
标签和
<result>
标签
@Result
中 属性介绍:
id
是否是主键字段
column
数据库的列名
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=
""
))
2
使用注解实现一对一复杂关系映射及延迟加载
需求:
加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载。(注解方式实现)
2.1
添加
User
实体类及
Account
实体类
/**** 

Title: User

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer userId;private String userName;private Date userBirthday;private String userSex;private String userAddress;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;}@Overridepublic String toString() {return "User [userId=" + userId + ", userName=" + userName + ", userBirthday="+ userBirthday + ", userSex="+ userSex + ", userAddress=" + userAddress + "]";}}/****

Title: Account

*

Description: 账户的实体类

*

Company: http://www.itheima.com/

*/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;}@Overridepublic String toString() {return "Account [id=" + id + ", uid=" + uid + ", money=" + money + "]";}}
2.2
添加账户的持久层接口并使用注解配置
/**** 

Title: IAccountDao

*

Description: 账户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IAccountDao {/*** 查询所有账户,采用延迟加载的方式查询账户的所属用户* @return*/@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(column="uid",property="user",one=@One(select="com.itheima.dao.IUserDao.findById",fetchType=FetchType.LAZY))})List
findAll();}
2.3
添加用户的持久层接口并使用注解配置
/**** 

Title: IUserDao

*

Description: 用户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 查询所有用户* @return*/@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")})List
findAll();/*** 根据 id 查询一个用户* @param userId* @return*/@Select("select * from user where id = #{uid} ")@ResultMap("userMap")User findById(Integer userId);}
2.4
测试一对一关联及延迟加载
/**** 

Title: AccountTest

*

Description: *

Company: http://www.itheima.com/

*/public class AccountTest {@Testpublic void testFindAll() {List
accounts = accountDao.findAll();//for(Account account : accounts) {//System.out.println(account);//System.out.println(account.getUser());//}
}
3
使用注解实现一对多复杂关系映射
需求:
查询用户信息时,也要查询他的账户列表。使用注解方式实现。
分析:
一个用户具有多个账户信息,所以形成了用户
(User)
与账户
(Account)
之间的一对多关系。
3.1 User
实体类加入
List<Account>
/**** 

Title: User

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer userId;private String userName;private Date userBirthday;private String userSex;private String userAddress;//一对多关系映射:主表方法应该包含一个从表方的集合引用private List
accounts;public List
getAccounts() {return accounts;}public void setAccounts(List
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;}@Overridepublic String toString() {return "User [userId=" + userId + ", userName=" + userName + ", userBirthday="+ userBirthday + ", userSex="+ userSex + ", userAddress=" + userAddress + "]";}}
3.2
编写用户的持久层接口并使用注解配置
/** ** 

Title: IUserDao

*

Description: 用户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IUserDao {/*** 查询所有用户* @return*/@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.itheima.dao.IAccountDao.findByUid",fetchType=FetchType.LAZY))})List
findAll();}

 @Many:

相当于<collection>的配置
select 属性:代表将要执行的 sql 语句
fetchType 属性:代表加载方式,一般如果要延迟加载都设置为 LAZY 的值

3.3
编写账户的持久层接口并使用注解配置
/**** 

Title: IAccountDao

*

Description: 账户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IAccountDao {/** * 根据用户 id 查询用户下的所有账户* @param userId* @return*/@Select("select * from account where uid = #{uid} ")List
findByUid(Integer userId);}
3.4
添加测试方法
/**** 

Title: MybatisAnnotationCRUDTest

*

Description: mybatis 的注解 crud 测试

*

Company: http://www.itheima.com/

*/public class UserTest {/*** 测试查询所有*/@Testpublic void testFindAll() {List
users = userDao.findAll();//for(User user : users) {//System.out.println("-----每个用户的内容-----");//System.out.println(user);//System.out.println(user.getAccounts());//}}private InputStream in;private SqlSessionFactory factory;private SqlSession session;private IUserDao userDao;@Before//junit 的注解public void init()throws Exception{//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建工厂SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(in);//3.创建 session session = factory.openSession();//4.创建代理对象userDao = session.getMapper(IUserDao.class);}@After//junit 的注解public void destroy()throws Exception {//提交事务session.commit();//释放资源session.close();//关闭流in.close();}}

通常来说,在一对多查多的时候用延迟加载,在一对一查一的时候通常用立即加载 

mybatis 基于注解的二级缓存

1
SqlMapConfig
中开启二级缓存支持
2
在持久层接口中使用注解配置二级缓存
/**** 

Title: IUserDao

*

Description: 用户的持久层接口

*

Company: http://www.itheima.com/

*/@CacheNamespace(blocking=true)//mybatis 基于注解方式实现配置二级缓存public interface IUserDao {}

 

 

 

 

转载地址:https://blog.csdn.net/m0_56426304/article/details/117921921 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Spring(一)
下一篇:MyBatis(三)

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年02月28日 15时16分20秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

mysql 关联更新_MySQL UPDATE多表关联更新 2019-04-21
mysql call_mysql的call用法 call调用函数的例子 2019-04-21
python参数验证_参数验证,Python中的最佳实践 2019-04-21
python画多层网络_在pymn中修改多层网络图 2019-04-21
java net 安卓_android -------- java.net.UnknownServiceException 2019-04-21
java 密钥 aes 解密_Java中AES加密解密以及签名校验 2019-04-21
java树转化成图_Java 转换一组数据为树型数据 2019-04-21
java 底层ppt_Java 如何设置 PPT 中的形状排列方式 具体内容 2019-04-21
mysql更新第5条记录_MYSQL中添加、更新、删除数据 2019-04-21
mysql service5.7_Mysql5.7服务下载安装 2019-04-21
mysql查看线程完整执行命令_MySQL-查看运行的线程-SHOW PROCESSLIST 2019-04-21
mysql 更新数据 字符串_批量替换 MySQL 指定字段中的字符串 2019-04-21
web开发 mysql安装_mysqlinstallerwebcommunity5.7.21.0.msi安装图文教程 2019-04-21
mysql concat 整数型_MySQL 数字类型转换函数(concat/cast) 2019-04-21
mysql单元格函数是_MySQL常用内置函数 2019-04-21
mysql 怎么字段分裂_你可以分裂/爆炸MySQL查询中的字段吗? 2019-04-21
mysql server卸载出错_Mysql卸载问题Start Server卡住报错解决方法 2019-04-21
全国省市区 mysql_2017全国省市区数据库【含三款数据库】 2019-04-21
druid加载MySQL驱动原理_你好,想知道mybatis+druid+jdbc 原理介绍? 2019-04-21
mysql 怎样链接jdbc_jdbc怎么链接mysql数据库 2019-04-21