mybatis 学习笔记
1. MyBatis 入门
-
ssm 框架与三层架构
-
MyBatis 是一个持久层框架,用 Java 语言编写,使用 ORM 思想(Object Relational Mapping) 对象关系映射,就是把数据库表和实体类以及实体类的属性对应起来(实体类中的属性和数据库表的字段名称保持一致),让我们操作实体类就实现操作数据库表。
-
MyBatis 中实体类需要实现 Serializable 接口。
-
MyBatis 的环境搭建
- 创建 maven 工程并导入坐标
1<dependency> 2 <groupId>org.mybatis</groupId> 3 <artifactId>mybatis</artifactId> 4 <version>3.4.5</version> 5</dependency> 6<dependency> 7 <groupId>mysql</groupId> 8 <artifactId>mysql-connector-java</artifactId> 9 <version>5.1.6</version> 10</dependency>
- 创建实体类(javaBean),和 dao 层的接口
- 创建 MyBatis 的主配置文件,名字没要求,在此 SqlMapConifg.xml
1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5<!-- mybatis的主配置文件 --> 6<configuration> 7 <!-- 配置环境 --> 8 <environments default="mysql"> 9 <!-- 配置mysql的环境--> 10 <environment id="mysql"> 11 <!-- 配置事务的类型--> 12 <transactionManager type="JDBC"></transactionManager> 13 <!-- 配置数据源(连接池) --> 14 <dataSource type="POOLED"> 15 <!-- 配置连接数据库的4个基本信息 --> 16 <property name="driver" value="com.mysql.jdbc.Driver"/> 17 <property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"/> 18 <property name="username" value="root"/> 19 <property name="password" value="1234"/> 20 </dataSource> 21 </environment> 22 </environments> 23 24 <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 --> 25 <!-- 在注册映射文件时使用<mapper resource="org/xx/demo/mapper/xx.xml"/>,不需要映射文件名和接口名一样 --> 26 <!-- 如果使用注解来配置,此处的 resources 应该用 class 来指定被注解的 dao 全限定类名 --> 27 <mappers> 28 <mapper resource="com/itheima/dao/IUserDao.xml"/> 29 </mappers> 30</configuration>
- 创建映射配置文件
1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5<mapper namespace="com.itheima.dao.IUserDao"> 6 <!--配置查询所有,id与接口中方法名一样--> 7 <select id="findAll" resultType="com.itheima.domain.User"> 8 select * from user 9 </select> 10</mapper>
- 创建 maven 工程并导入坐标
-
环境搭建的注意事项
- 在 MyBatis 中持久层的操作接口名称也和映射文件也叫做 Mapper(以前为 dao)
- 在 resources 中创建目录的时候,和包不一样,需一级一级创建
- MyBatis 映射文件的位置必须和 dao 接口的包结构相同
- 映射配置文件的 mapper 标签 namespace 属性的取值必须是 dao 接口的全限定类名
- 映射配置文件的操作配置(select),id 属性的取值必须是 dao 接口的方法名
- 当我们遵循上述后 3 点之后,在开发中无需再写 dao 的实现类
-
入门案例
1package com.itheima.test; 2 3import com.itheima.dao.IUserDao; 4import com.itheima.domain.User; 5import org.apache.ibatis.io.Resources; 6import org.apache.ibatis.session.SqlSession; 7import org.apache.ibatis.session.SqlSessionFactory; 8import org.apache.ibatis.session.SqlSessionFactoryBuilder; 9 10import java.io.InputStream; 11import java.util.List; 12 13public class MybatisTest { 14 public static void main(String[] args)throws Exception { 15 //1.读取配置文件 16 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); 17 //2.创建SqlSessionFactory工厂 18 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 19 SqlSessionFactory factory = builder.build(in); 20 //3.使用工厂生产SqlSession对象,操作数据库对象 21 SqlSession session = factory.openSession(); 22 //4.使用SqlSession创建Dao接口的代理对象,代理模式 23 IUserDao userDao = session.getMapper(IUserDao.class); 24 //5.使用代理对象执行方法 25 List<User> users = userDao.findAll(); 26 for(User user : users){ 27 System.out.println(user); 28 } 29 //6.释放资源 30 session.close(); 31 in.close(); 32 } 33}
-
使用注解的时候
- 不需要映射配置文件
- 主配置文件中
<mapper class="全限定类型"/>
- 接口上使用注解
@Select("select * from user")
-
MyBatis 支持写 dao 实现类,一般不用,不简便。
- 配置映射配置文件
- 写 dao 的实现类,通过读取配置文件的 SQL 语句来查询
1public class UserDaoImpl implements IUserDao { 2 private SqlSessionFactory factory; 3 4 public UserDaoImpl(SqlSessionFactory factory) { 5 this.factory = factory; 6 } 7 8 public List<User> findAll() { 9 SqlSession session = factory.openSession(); 10 List<User> users = session.selectList("com.itheima.dao.IUserDao.findAll"); 11 session.close(); 12 return users; 13 } 14}
- 测试类
1public static void main(String[] args) throws Exception { 2 //1.读取配置文件 3 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); 4 //2.创建SqlSessionFactory工厂 5 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 6 SqlSessionFactory factory = builder.build(in); 7 //3.使用工厂创建dao对象 8 UserDaoImpl userDao = new UserDaoImpl(factory); 9 //4.使用代理对象执行方法 10 List<User> users = userDao.findAll(); 11 for (User user : users) { 12 System.out.println(user); 13 } 14 //5.释放资源 15 in.close(); 16 }
2. 自定义 MyBatis 框架
- MyBatis 在使用代理 dao 的方式实现增删改查时做了什么事情
- 创建代理对象
- 在代理对象中调用 selectList 方法
- 执行查询所有分析
- 创建代理对象的分析
- 自定义 MyBatis 开发流程图
3. MyBatis 的 CRUD
-
CRUD 使用要求
- 持久层接口和持久层接口的映射配置必须在相同的包下
- 持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
- SQL 语句的配置标签
<select>,<insert>,<delete>,<update>
的 id 属性必须和持久层接口的方法名相同。
-
MyBatis 动态执行 SQL。
-
MyBatis 默认手动提交事务,需要
sqlSession.commit();
-
insert 操作:
1<insert id="saveUser" parameterType="pers.ylq.domain.User"> 2 <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER"> 3 select last_insert_id(); 4 </selectKey> 5 insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday}); 6</insert>
- parameterType 属性:用于指定传入参数的类型,全类名。
- resultType 属性:用于指定结果集的类型(查询的每条结果要封装的类型)。简单数据类型可以随意写,能识别就好,比如 int、Integer、String、java.liang.String ,如果结果是一个类,则需要写全类名。
- SQL 语句中使用
#{}
字符 :- 它代表占位符,相当于原来 JDBC 部分所学的
?
,都是用于执行语句时替换实际的数据。具体的数据是由#{}
里面的内容决定的。 - 语法格式就是使用
#{对象.属性}
的方式,#{user.username}
它会先去找 user 对象,然后在 user 对象中找到 username 属性,并调用getUsername()
方法把值取出来。但是我们在 parameterType 属性上指定了实体类名称,所以可以省略user.
而直接写 username。
- 它代表占位符,相当于原来 JDBC 部分所学的
- selectKey 的作用:配置保存时获取插入的 id,id 为自增长,keyProperty 表示返回给对象的哪一个属性,keyColumn 指向表中的主键,可省略,order 表示在什么时候执行。
select last_insert_id()
查询上一条自增长数据的 id。
-
update 操作
1<update id="updateUser" parameterType="pers.ylq.domain.User"> 2 update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}; 3</update>
#{}
中的值代表 User 对象中的属性。
-
delete 操作
1<delete id="deleteUser" parameterType="int"> 2 delete from user where id=#{id}; 3</delete>
- 由于参数类型是基本类型,
#{}
中内容可随意填写。
- 由于参数类型是基本类型,
-
select 操作:
1List<User> findAll(); 2<select id="findAll" resultType="pers.ylq.domain.User"> 3 select * from user; 4</select>
- resultType 为查询的结果封装的类型,不是方法的返回值类型。
-
模糊查询:
1List<User> findByName(String username); 2<select id="findByName" parameterType="String" resultType="pers.ylq.domain.User"> 3 select * from user where username like #{name}; 4</select> 5List<User> users = userDao.findByName("%王%");
- 在传递参数的时候传递
%
可实现动态模糊查询
1<select id="findByName" parameterType="String" resultType="pers.ylq.domain.User"> 2 select * from user where username like concat('%',#{name},'%'); 3</select> 4List<User> users = userDao.findByName("王");
- 使用 concat 函数连接参数。
1List<User> users = userDao.findByName("王"); 2<select id="findByName" parameterType="String" resultType="pers.ylq.domain.User"> 3 select * from user where username like '%${value}%'; 4</select>
- 通过
${}
可以将 parameterType 传入的内容拼接在 SQL 中且不进行 JDBC 类型转换,${}
可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值 ,${}
括号中只能是 value。
1public class QueryVo implements Serializable { 2 private User user; 3 public User getUser() { return user; } 4 public void setUser(User user) { this.user = user; } 5} 6 7<select id="findUserByVo" resultType="pers.ylq.domain.User" parameterType="pers.ylq.domain.QueryVo"> 8 select * from user where username like #{user.username}; 9</select> 10 11QueryVo vo = new QueryVo(); 12User user = new User(); 13vo.setUser(user); 14user.setUsername("%王%"); 15List<User> users = userDao.findUserByVo(vo);
- 查询的参数对象中存有对象
- 在传递参数的时候传递
-
MyBatis 传递多个参数
- 传递多个参数的时候,不能使用 parameterType 指定参数类型。
- 可以通过参数传递顺序取值
1<select id="findByNameAndAddress" resultType="pers.ylq.domain.User"> 2 select * from user where username = #{arg0} and address = #{arg1}; 3</select> 4 5List<User> users = userDao.findByNameAndAddress("老王", "北京");
- 在 dao 层通过注解 @Param 实现多参传递,注解中的属性为参数的名字,在 XML 中通过此名字获取参数。
1List<User> findByNameAndAddress(@Param("username") String username, @Param("address") String address); 2 3<select id="findByNameAndAddress" resultType="pers.ylq.domain.User"> 4 select * from user where username = #{username} and address = #{address}; 5</select> 6 7List<User> users = userDao.findByNameAndAddress("老王", "北京");
-
解决实体类属性和数据库列名不对应的两种方式
- 第一种:为查询出的数据用 as 关键字起别名,别名跟实体类中名字一样,即可成功封装为对象。
- 第二种:建立属性名和列名的对应关系,然后使用 resultMap 属性,指向此对应表即可
1<!-- 配置 查询结果的列名和实体类的属性名的对应关系 --> 2<!-- id为对应表的唯一标识,可以随意起名 --> 3<resultMap id="userMap" type="pers.ylq.damain.User"> 4 <!-- 主键字段的对应 --> 5 <id property="userId" column="id"></id> 6 <!--非主键字段的对应--> 7 <result property="userName" column="username"></result> 8 <result property="userAddress" column="address"></result> 9 <result property="userSex" column="sex"></result> 10 <result property="userBirthday" column="birthday"></result> 11</resultMap> 12 13<select id="findById" parameterType="INT" resultMap="userMap"> 14 select * from user where id = #{uid} 15</select>
4. 主配置文件的配置和顺序
-
properties 标签:配置属性
-
1<properties> 2 <property name="driver" value="com.mysql.jdbc.Driver"/> 3 <property name="url" value="jdbc:mysql://localhost:3306/eesy-mybatis"/> 4 <property name="username" value="root"/> 5 <property name="password" value="123456"/> 6</properties> 7<environments default="mysql"> 8 <environment id="mysql"> 9 <transactionManager type="JDBC"></transactionManager> 10 <dataSource type="POOLED"> 11 <property name="url" value="${url}"/> 12 <property name="driver" value="${driver}"/> 13 <property name="username" value="${username}"/> 14 <property name="password" value="${password}"/> 15 </dataSource> 16 </environment> 17</environments>
配置完成之后,可在下面通过
${name}
取值。 -
resources 属性:用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
1<properties resource="jdbcConfig.properties"> 2</properties> 3 4<properties resource="pers/ylq/dao/jdbcConfig.properties"> 5</properties>
此文件若处于类的根路径下,因此直接写文件名就行。
下面依旧通过${name}
来取值。 -
url 属性
1<properties url="file:///C:/Users/10766/Desktop/jdbcConfig.properties"> 2</properties>
URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
它的写法:http://localhost:8080/mybatisserver/demo1Servlet 协议 主机 端口 URI
URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
-
-
settings 标签:对 MyBatis 进行一些设置,比如延迟加载。
-
typeAliases 标签:为类型起别名
1<typeAliases> 2 <typeAlias type="pers.ylq.domain.User" alias="user"></typeAlias> 3</typeAliases>
type 为实体类类型,alias 为别名,起了别名之后,不再区分大小写,在映射配置文件中可以用别名。
package 标签:用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写。1<typeAliases> 2 <package name="pers.ylq.domain"></package> 3</typeAliases>
-
environments 标签(环境集合属性对象)
- environment(环境子属性对象)
- transactionManager(事务管理)
- dataSource(数据源)
- environment(环境子属性对象)
-
mappers 标签
- mapper:指定映射的接口或者 XML 文件,因为两者路径一样,指定哪个都行。
- resource:指定映射配置文件
- class:指定 mapper 接口类路径,此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
- package:用于指定 dao 接口所在的包,当指定了之后就不需要再写 mapper 以及 resource 或者 class 了。此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
- mapper:指定映射的接口或者 XML 文件,因为两者路径一样,指定哪个都行。
5. 执行过程分析(了解)
- 分析编写 dao 实现类 MyBatis 的执行过程
- 分析代理 dao 的执行过程
6. MyBatis 连接池及事务
- MyBatis 提供了 3 中连接池的配置方式
- 配置的位置:主配置文件的 DataSource 标签,type 属性。
- 取值:
- POOLED 采用传统的
javax.sql.DataSource
规范中的连接池,MyBatis 有针对规范的实现。 - UNPOOLED 采用传统的获取连接的方式,虽然也实现了 DataSource 接口,但并没有使用池的思想。
- JNDI 采用服务器提供的 JNDI 技术实现,来获取 DataSource 对象,不同服务器所能拿到的 DataSource 是不一样的。Tomcat 获取的连接池就是 dbcp 连接池。
注意:如果不是 Web 或者 maven 的 war 工程,是不能使用的。
- POOLED 采用传统的
- MyBatis 中事务通过 sqlsession 对象的 commit 方法和 rollback 方法实现事务的提交和回滚。
SqlSession openSession(boolean var1);
可通过设置参数为 true 来自动提交事务。
7. 动态 SQL
-
if 标签
1<select id="findUserByCondition" parameterType="User" resultMap="userMap"> 2 select * from user where 1 = 1 3 <if test="username!=null"> 4 and username=#{username} 5 </if> 6</select>
-
where 标签
1<select id="findUserByCondition" parameterType="User" resultMap="userMap"> 2 select * from user 3 <where> 4 <if test="username!=null"> 5 and username=#{username} 6 </if> 7 <if test="sex!=null"> 8 and sex=#{sex} 9 </if> 10 </where> 11</select>
-
foreach 标签
1<select id="findUserByList" resultMap="userMap"> 2 select * from user 3 <where> 4 <foreach collection="list" open="id in(" close=")" item="id" separator=","> 5 #{id} 6 </foreach> 7 </where> 8</select>
- 如果传入的是单参数且参数类型是一个 List 的时候,collection 属性值为 list
- 如果传入的是单参数且参数类型是一个 array 数组的时候,collection 的属性值为 array
-
SQL 标签:声明 SQL 语句,下面可以直接引入
1<sql id="defaultUser"> 2 select * from user 3</sql> 4<select id="findAll" resultMap="userMap"> 5 <include refid="defaultUser"></include> 6</select>
8. 多表查询
- 一对一查询(多对一查询)
-
有两个表,User 表和 Account 表,Account 表中有外键 uid 于 User 中 id 对应。
-
方式一:定义一个新的类,AccountUser extends Account,还包含用户的信息字段,将返回结果封装到此类中。
-
方式二:在 Account 类中加入 User 类的对象作为 Account 类的一个属性,定义一个 resultMap
1<resultMap id="accountUserMap" type="Account"> 2 <id property="id" column="aid"/> 3 <result property="uid" column="uid"/> 4 <result property="money" column="money"/> 5 6 <association property="user" javaType="User"> 7 <id property="id" column="id"/> 8 <result property="username" column="username"/> 9 <result property="address" column="address"/> 10 <result property="sex" column="sex"/> 11 <result property="birthday" column="birthday"/> 12 </association> 13</resultMap>
查询结果的 resultMap 指向此映射关系。
-
- 一对多查询:
- User 类中加入
List<Account> accounts;
1<resultMap id="userAccountMap" type="User"> 2 <id property="id" column="id"/> 3 <result property="username" column="username"/> 4 <result property="address" column="address"/> 5 <result property="sex" column="sex"/> 6 <result property="birthday" column="birthday"/> 7 8 <collection property="accounts" ofType="Account"> 9 <id property="id" column="aid"/> 10 <result property="uid" column="uid"/> 11 <result property="money" column="money"/> 12 </collection> 13</resultMap> 14 15<select id="findAll" resultMap="userAccountMap"> 16 SELECT u.*,a.id aid,uid,money FROM USER u LEFT JOIN account a ON u.id=a.uid; 17</select>
- User 类中加入
- 多对多查询:在两个表的实体类中分别加入对方实体类的 List 集合,在各自配置文件配置 resultMap 查询即可。
9. MyBatis 延迟加载
- 延迟加载:需要数据的时候才加载,不需要不加载。
- 实现:先从单表查询,需要时再去从关联表关联查询。
- 主配置文件配置:
1<settings> 2 <!-- 延迟加载全局开关 --> 3 <setting name="lazyLoadingEnabled" value="true"/> 4 <!-- 开启时,任何方法调用都会加载该对象所有属性,否则,按需加载,默认false(true in<=3.4.1) --> 5 <setting name="aggressiveLazyLoading" value="false"/> 6</settings>
- 实体类配置文件:
-
一对一实现延迟加载,association 实现
1<resultMap id="accountUserMap" type="Account"> 2 <id property="id" column="id"/> 3 <result property="uid" column="uid"/> 4 <result property="money" column="money"/> 5 <association property="user" column="uid" javaType="User" 6 select="pers.ylq.dao.IUserDao.findById"/> 7</resultMap> 8 9<select id="findAll" resultMap="accountUserMap"> 10 select * from account 11</select>
select 标签声明延迟加载调用的方法,clomu 为所传递的参数,property 指向实体类中的成员变量
-
一对多实现延迟加载,collection 实现
1<resultMap id="userMap" type="user"> 2 <id property="id" column="id"/> 3 <result property="username" column="username"/> 4 <result property="address" column="address"/> 5 <result property="sex" column="sex"/> 6 <result property="birthday" column="birthday"/> 7 <collection property="accounts" ofType="Account" column="id" 8 select="pers.ylq.dao.IAccountDao.findAccountById"/> 9</resultMap> 10 11<select id="findAll" resultMap="userMap"> 12 select * from user 13</select>
-
10. 缓存
- MyBatis 中有一级缓存和二级缓存
- 一级缓存:
- 它指的是 MyBatis 中 SqlSession 对象的缓存。
- 当我们执行查询之后,查询的结果会同时存入到 SqlSession 为我们提供一块区域中。
- 该区域的结构是一个 Map。当我们再次查询同样的数据,MyBatis 会先去 sqlsession 中查询是否有,有的话直接拿出来用。
- 当 SqlSession 对象消失时,MyBatis 的一级缓存也就消失了。
- 一级缓存的清空:一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close() 等方法时,就会清空一级缓存。
- 二级缓存:它指的是 MyBatis 中 SqlSessionFactory 对象的缓存。由同一个 SqlSessionFactory 对象创建的 SqlSession 共享其缓存。
- 二级缓存的使用步骤:
- 让 MyBatis 框架支持二级缓存(在主配置文件中配置),默认为 true
1<settings> 2 <setting name="cacheEnabled" value="true"/> 3</settings>
- 让当前的映射文件支持二级缓存(在映射配置文件中配置),
<cache/>
- 让当前的操作支持二级缓存(在 select 标签中配置),
useCache=true
- 让 MyBatis 框架支持二级缓存(在主配置文件中配置),默认为 true
- 如果有 SqlSession 去执行相同 mapper 映射下 SQL 语句,执行 commit 提交,将会清空该 mapper 映射下的二级缓存区域的数据。
- 二级缓存存的是数据,而不是对象,从缓存中查询数据的时候将数据封装进对象,所以多次查询获取的对象的地址是不同的。
11. MyBatis 注解开发
-
在 MyBatis 中,CRUD 共 4 个注解
- @Select
- @Insert
- @Update
- @Delete
-
一个接口只能使用注解或 XML 文件,无法共存,即使用注解又使用 XML 会报错。即使 mapper 中使用 class 指向注解也会报错。
-
当实体类的成员变量名和数据库字段名不对应的时候,可以使用 @Results 来配置对应关系
1@Select("select * from user") 2@Results(id = "userMap", value = { 3 @Result(id = true, property = "userId", column = "id"), 4 @Result(property = "userName", column = "username"), 5 @Result(property = "userAddress", column = "address"), 6 @Result(property = "userSex", column = "sex"), 7 @Result(property = "userBirthday", column = "birthday"), 8}) 9List<User1> findAll();
- id 为该对应关系的唯一标识,供别的方法引用。
- @Result 中的 id=true,代表其为主键
- @Result 实现结果集的封装。
- 别的方法可通过 @ResultMap("id") 引用此映射关系
-
一对一查询配置(多对一)
-
MyBatis 中没有多对一的概念,多对一是通过一对一的方式来实现的。
-
首先在 Account 实体类中添加 User 变量,生成 getter 和 setter 方法。
-
在接口中使用注解配置 @Result
1@Select("select * from account") 2@Results(id = "accountMap", value = { 3 @Result(id = true, property = "id", column = "id"), 4 @Result(property = "uid", column = "uid"), 5 @Result(property = "money", column = "money"), 6 @Result(property = "user",column = "uid",one = @One(select = "pers.ylq.dao.IUserDao.findById",fetchType = FetchType.EAGER)) 7}) 8List<Account> findAll();
- 最后一个 @Result 中,property 代表实体类中的变量,column 代表要传入的数据库的列名
- @Result 中有:
One one() default @One;
和Many many() default @Many;
,one 代表一对一,many 代表一对多,代表此对象对应几个对象。 - @One 中的属性 select 代表要执行的语句的唯一标识。
- fetchType 有三个取值:LAZY(延迟加载),EAGER(立即加载),DEFAULT(默认)。
-
-
一对多查询配置:
-
在 User 实体类中添加
private List<Account> accounts;
-
配置接口的注解
1@Select("select * from user") 2@Results(id = "userMap", value = { 3 @Result(id = true, property = "id", column = "id"), 4 @Result(property = "username", column = "username"), 5 @Result(property = "address", column = "address"), 6 @Result(property = "sex", column = "sex"), 7 @Result(property = "birthday", column = "birthday"), 8 @Result(property = "accounts",column = "id", 9 many = @Many(select = "pers.ylq.dao.IAccountDao.findAccountByUid", 10 fetchType = FetchType.LAZY)) 11}) 12List<User> findAll();
- many 代表一对多的关系。
- FetchType.LAZY 代表延迟加载,此属性代替了在主配置文件中 settings 中的配置。
-
-
注解使用二级缓存:在 dao 层的接口上配置
@CacheNamespace(blocking=true)
-
常用注解说明:
- @Insert:实现新增
- @Update:实现更新
- @Delete:实现删除
- @Select:实现查询
- @Result:实现结果集封装
- @Results:可以与 @Result 一起使用,封装多个结果集
- @ResultMap:实现引用 @Results 定义的封装
- @One:实现一对一结果集封装
- @Many:实现一对多结果集封装
- @SelectProvider: 实现动态 SQL 映射
- @CacheNamespace:实现注解二级缓存的使用
-
@SelectProvider: 实现动态 SQL 映射
@SelectProvider(type = Provider.class,method = "selectProvider")
指定了一个类的 class 和类中的方法。- 此方法返回一个字符串,即为所要执行的 SQL 语句。
-
1public class Provider { 2 public String selectProvider(String name) { 3 String sql = "select * from user where 1=1 "; 4 if (name != null && !name.equals(" ")) { 5 sql += " and username=#{name} "; 6 } 7 return sql; 8 } 9}
12. mapper 层注解
- @Mapper, mybatis 注解
- @Repository, sping 注解
相同点:
@Mapper 和 @Repository 都是作用在 dao 层接口,使得其生成代理对象 bean,交给 spring 容器管理
不同点:
@Mapper 不需要配置扫描地址,可以单独使用,如果有多个mapper 文件的话,可以在项目启动类中加入 @MapperScan(“mapper文件所在包”),这样就不需要每个 mapper 文件都加 @Mapper 注解了。
@Repository 需要配置扫描地址
但在 idea 中,使用 @Repository 可以消除在业务层中注入 mapper 对象时的错误