文章目录
MyBatis 提供了XML配置和注解配置两种方式,这里介绍注解配置方式。
一、Mybatis常用注解
注解 | 释义 |
---|---|
@Select | 映射查询的SQL语句 |
@SelectProvider | Select的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。 |
@ Insert | 映射插入的SQL语句 |
@InsertProvider | Insert的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。 |
@Update | 映射更新的SQL语句 |
@UpdateProvider | Update的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。 |
@Delete | 映射删除的SQL语句 |
@DeleteProvider | Delete的动态SQL映射。允许指定一个类名和一个方法在执行时返回运行的查询语句。有type(类的完全限定名)和method(该类中的指定映射的方法名)两个属性。 |
@Results | 多个结果集映射列表 |
@Result | 在列和属性之间的单独结果映射 |
@Options | 提供配置选项的附加值 |
@One | 复杂类型的单独属性值映射。与XML配置中的 < association > 类似 |
@Many | 复杂类型结合属性映射 。与XML配置中的 < collection> 类似 |
@Param | 当映射器需要多哥参数是,可以用于给每个参数取一个名字。否则多参数默认会以他们的顺序位置和sql语句表达式中的顺序进行映射。 |
二、Sql语句的直接映射:
1. 举例
表结构如下。
定义一个实体类如下
// 必须加上改注解,否则会报错
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
public class User implements Serializable{
private int id;
private String name;
private String pwd;
private int parentId;
private User parentUser;
private List<User> sonUsers;
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
public User getParentUser() {
return parentUser;
}
public void setParentUser(User parentUser) {
this.parentUser = parentUser;
}
public List<User> getSonUsers() {
return sonUsers;
}
public void setSonUsers(List<User> sonUsers) {
this.sonUsers = sonUsers;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
Mapper文件如下:
@Mapper
public interface UserMapper {
/**
* 查找用户,包括其上下节点
* @param id
* @return
*/
@Select("select * from user where id = #{id}")
@Results({
// id = true 说明他是主键 。User类中的id属性对应表中的id列。下同。
// 这是为了指定别名,其实名称相同不指定也可以
@Result(id = true, column = "id", property = "id"),
@Result(column = "pwd", property = "pwd"),
@Result(column = "name", property = "name"),
@Result(column = "name", property = "name"),
// @Many 则将通过 selectSonUser 方法查询到其子类用户。
// column = "id" 作用 是 对selectSonUser方法来说传入的参数是selectUser 锁查询出来的 id 列
// fetchType 指定懒加载
// 即User类中的sonUsers 属性从selectSonUser中查询出来,selectSonUser传入的参数是当前的id列
@Result(column = "id", property = "sonUsers", many = @Many(
select = "com.kingfish.dao.UserMapper.selectSonUser", fetchType = FetchType.LAZY
)),
// @One 则将通过 selectParentUser 方法查询到其父类用户
@Result(column = "parentId", property = "parentUser", one = @One(
select = "com.kingfish.dao.UserMapper.selectParentUser", fetchType = FetchType.LAZY
))
})
List<User> selectUser(int id);
/**
* 查找儿子节点
* @param id
* @return
*/
@Select("select * from user where parentId = #{id}")
@Results({
@Result(column = "id", property = "sonUsers", many = @Many(
select = "com.kingfish.dao.UserMapper.selectSonUser", fetchType = FetchType.LAZY
)),
@Result(column = "parentId", property = "parentUser", one = @One(
select = "com.kingfish.dao.UserMapper.selectParentUser", fetchType = FetchType.LAZY
))
})
List<User> selectSonUser(int id);
/**
* 查找父节点
* @param parentId
* @return
*/
@Select("select * from user where id = #{parentId}")
User selectParentUser(int parentId);
}
访问接口调用selectUser方法.。得到结果如下。
插入数据演示:
Mapper映射
待插入数据
插入后结果
更新和删除类似,下面不再演示。
2. MyBatis一对多,一对一关系映射属性
association 的属性 | 具体意思 |
---|---|
column | 表示数据库表的列名。在子查询中会将父表中的该列名的值作为参数传递到子查询中 |
property | 表示返回的类型的属性名,属性名为user |
javaType | 表示表示该属性对应的类型,本例是一个User类型 |
select | 表示一条查询语句,将查询到的数据封装到property指定的属性中 |
fetchType | 取值有eager和lazy。分别代表立即加载和延迟加载。主要为性能考虑,如果此次查询中一定会查询userList可以设置为立即加载。如果不一定使用,可以使用延迟加载。正常情况下,都应设为lazy |
collection 的属性 | 具体意思 |
---|---|
column | 表示数据库表的列名。在子查询中会将父表中的该列名的值作为参数传递到子查询中 |
property | 表示返回的类型的属性名,属性名为user |
javaType | 表示表示该属性对应的类型,本例是一个User类型 |
ofType | List集合中的实例对象类型 |
select | 表示一条查询语句,将查询到的数据封装到property指定的属性中 |
fetchType | 取值有eager和lazy。分别代表立即加载和延迟加载。主要为性能考虑,如果此次查询中一定会查询userList可以设置为立即加载。如果不一定使用,可以使用延迟加载。正常情况下,都应设为lazy |
要延迟加载时,必须要在mybaitis配置文件中加上
<!- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"></setting>
<setting name="aggressiveLazyLoading" value="false"></setting>
具体如下:
<?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>
<settings>
<!--使用jdbc的getGeneratekeys获取自增主键值-->
<setting name="useGeneratedKeys" value="true"/>
<!--使用列别名替换别名 默认true-->
<setting name="useColumnLabel" value="true"/>
<!--开启驼峰命名转换Table:create_time到 Entity(createTime)-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 打印日志 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"></setting>
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
<typeAliases>
<typeAlias type="com.kingfish.pojo.User" alias="user"></typeAlias>
</typeAliases>
</configuration>
三、Sql语句的动态映射
Mybatis的注解也支持动态,同时提供了对应的一些SQL类的常用方法。基本覆盖了日常使用。
Sql类提供的方法:
动态sql provider方法可以接收以下参数:
- 无参数
- java对象
- java.util.Map
- 需要创建一个动态Sql类。并创建对应生成的sql方法,这里随便创建了一个。
public class UserProvider {
// 将会拼接生成对应的sql语句。可以通过代码来模拟XML中的各种判断情况,实现动态sql
public String selectUser(Integer id) {
return new SQL() {
{
SELECT("*");
FROM("user");
if (id != null) {
WHERE("id = #{id}");
}
}
}.toString();
}
}
改造一下刚才的selectUser方法。将使用 @Select(注释掉,使用 @SelectProvider 注解
@SelectProvider : type 属性指定了动态sql类,method指定了sql类里面对应词查询的方法。
// @Select("select * from user where id = #{id}")
@SelectProvider(type = UserProvider.class, method = "selectUser")
@Results({
// id = true 说明他是主键 。User类中的id属性对应表中的id列。下同。
// 这是为了指定别名,其实名称相同不指定也可以
@Result(id = true, column = "id", property = "id"),
@Result(column = "pwd", property = "pwd"),
@Result(column = "name", property = "name"),
@Result(column = "name", property = "name"),
// @Many 则将通过 selectSonUser 方法查询到其子类用户。
// column = "id" 作用 是 对selectSonUser方法来说传入的参数是selectUser 锁查询出来的 id 列
// fetchType 指定懒加载
@Result(column = "id", property = "sonUsers", many = @Many(
select = "com.kingfish.dao.UserMapper.selectSonUser", fetchType = FetchType.LAZY
)),
// @One 则将通过 selectParentUser 方法查询到其父类用户
@Result(column = "parentId", property = "parentUser", one = @One(
select = "com.kingfish.dao.UserMapper.selectParentUser", fetchType = FetchType.LAZY
))
})
测试没问题。
补: 一对多的XML形式映射(仅用举例)
<resultMap id="loadUserByUsernameResultMap" type="com.example.common.config.security.MyUserDetails">
<collection property="roleIds" select="com.example.dao.UserRoleMapper.selectRoleByUserId"
column="user_id" ></collection>
</resultMap>
<select id="loadUserByUsername" resultMap="loadUserByUsernameResultMap">
select
<include refid="Base_Column_List"></include>
from user u
where u.user_id = #{username};
</select>