Springboot - 整合mybatis
1. 整合 mybatis
1.1 配置mybatis
SpringBoot官方并没有提供Mybatis的启动器,不过Mybatis官网自己实现了:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
配置
# mybatis 别名扫描
mybatis.type-aliases-package=com.murphy.domain
# mybatis .xml文件位置
mybatis.mapper-locations=classpath:mappers/*.xml
实体类 - User.java
/**
* User- 实体类
*
* @author murphy
* @since 2021/8/14 11:15 下午
*/
public class User implements Serializable {
private Long id;
// 用户名 - 自动转换下划线到驼峰命名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别:1男性 - 2女性
private Integer sex;
// 出生日期
private Date birthday;
// 创建时间
private Date created;
// 更新时间
private Date updated;
// 备注
private String note;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", birthday=" + birthday +
", created=" + created +
", updated=" + updated +
", note='" + note + '\'' +
'}';
}
// 省略 Getter、Setter 方法
}
接口
/**
* User - Dao类
*
* @author murphy
* @since 2021/8/15 12:08 上午
*/
public interface UserDao {
public List<User> findAll();
}
映射文件
<?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.murphy.dao.UserDao">
<select id="findAll" resultType="User">
select * from SpringBoot_user
</select>
</mapper>
Mapper的加载接口代理对象方式有 2 种
- 第一种:使用
@Mapper
注解 - (不推荐)
需要注意,这里没有配置mapper
接口扫描包,因此我们需要给每一个Mapper接口添加@Mapper
注解,才能被识别。
/**
* User - Dao类
*
* @author murphy
* @since 2021/8/15 12:08 上午
*/
@Mapper
public interface UserDao {
public List<User> findAll();
}
- 第二种:设置
MapperScan
,注解扫描的包 - (推荐)
@MapperScan("dao所在的包")
,自动搜索包中的接口,产生dao的代理对象
/**
* 启动器
*
* @author murphy
* @since 2021/8/13 6:33 下午
*/
@SpringBootApplication
@MapperScan("com.murphy.dao")
public class Application {
/**
* 启动类
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest extends TestCase {
@Autowired
private UserDao userDao;
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
users.forEach(user -> System.out.println(user));
}
}
1.2 通用mapper
概念
- 使用Mybatis时,最大的问题是,要写大量的重复SQL语句在
xml
文件中,除了特殊的业务逻辑SQL语句之外,还有大量结构类似的增删改查SQL。而且,当数据库表结构改动时,对应的所有SQL以及实体类都需要更改。这大量增加了程序员的负担。 - 避免重复书写CRUD映射的框架有两个:
- 通用
mybatis(tk mybatis)
mybatis plus
,通能更加强大
- 通用
通用Mapper的作者也为自己的插件编写了启动器,我们直接引入即可:
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
实体类 —— tk mybatis
实体类使用的注解是jpa注解
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;
/**
* User- 实体类
*
* @author murphy
* @since 2021/8/14 11:15 下午
*/
@Table(name = "SpringBoot_user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 用户名 - 自动转换下划线到驼峰命名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别:1男性 - 2女性
private Integer sex;
// 出生日期
private Date birthday;
// 创建时间
private Date created;
// 更新时间
private Date updated;
// 备注
private String note;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", birthday=" + birthday +
", created=" + created +
", updated=" + updated +
", note='" + note + '\'' +
'}';
}
// 省略 Getter/Setter 方法
}
注意事项:
-
默认
表名=类名
,字段名=属性名
-
表名可以使用
@Table(name = "tableName")
进行指定 -
@Column(name = "fieldName")
指定 -
使用
@Transient
注解表示跟字段不进行映射
<?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.murphy.dao.UserMapper">
</mapper>
自定义映射文件
映射复杂方法 resources/mappers/UserMapper.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.murphy.dao.UserMapper">
<select id="findByUser" resultType="User">
select * from Springboot_Study.SpringBoot_user
<where>
<if test="name != null">
name like '%${name}%'
</if>
<if test="note != null">
and note like '%${note}%'
</if>
</where>
</select>
</mapper>
一旦继承了Mapper,继承的Mapper就拥有了Mapper所有的通用方法:
Select 方法:List<T> select(T record);
—— 说明:根据实体中的属性值进行查询,查询条件使用等号
-
方法:
T selectByPrimaryKey(Object key);
-
说明:根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号
-
方法:
List<T> selectAll();
-
说明:查询全部结果,
select(null)
方法能达到同样的效果 -
方法:
T selectOne(T record);
-
说明:根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
-
方法:
int selectCount(T record);
-
说明:根据实体中的属性查询总数,查询条件使用等号
Insert 方法:int insert(T record);
—— 说明:保存一个实体,null
的属性也会保存,不会使用数据库默认值
- 方法:
int insertSelective(T record);
- 说明:保存一个实体,
null
的属性不会保存,会使用数据库默认值
Update 方法:int updateByPrimaryKey(T record);
—— 说明:根据主键更新实体全部字段,null
值会被更新
- 方法:
int updateByPrimaryKeySelective(T record);
- 说明:根据主键更新属性不为
null
的值
Delete 方法:int delete(T record);
—— 说明:根据实体属性作为条件进行删除,查询条件使用等号
- 方法:
int deleteByPrimaryKey(Object key);
- 说明:根据主键字段进行删除,方法参数必须包含完整的主键属性
Example 方法:List<T> selectByExample(Object example);
—— 说明:根据Example条件进行查询,支持通过Example类指定查询列,通过selectProperties
方法指定查询列
-
方法:
int selectCountByExample(Object example);
-
说明:根据Example条件进行查询总数
-
方法:
int updateByExample(@Param("record") T record, @Param("example") Object example);
-
说明:根据
Example
条件更新实体record
包含的全部属性,null值会被更新 -
方法:
int updateByExampleSelective(@Param("record") T record, @Param("example") Object example);
-
说明:根据Example条件更新实体
record
包含的不是null
的属性值 -
方法:
int deleteByExample(Object example);
-
说明:根据Example条件删除数据
注意要把MapperScan类改成tk-mybatis
构件的类
import tk.mybatis.mapper.entity.Example;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest extends TestCase {
}
注意:必须使用tk mybatis
的MapperScan
启动测试 - 测试类
import com.murphy.domain.User;
import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import tk.mybatis.mapper.entity.Example;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest extends TestCase {
@Resource
private UserMapper userMapper;
@Test
public void testSelectAll() {
userMapper.selectAll().forEach(user -> System.out.println(user));
}
@Test
public void testSelectById() {
User user = userMapper.selectByPrimaryKey(5);
System.out.println(user);
}
/**
* 模糊查询
*/
@Test
public void testSelectByExample() {
Example example = new Example(User.class);
example.createCriteria().andLike("name","%咕%");
userMapper.selectByExample(example).forEach(user -> System.out.println(user));
}
/**
* 自定义XML映射
*/
@Test
public void testFindByUser() {
User user = new User();
user.setName("墨");
user.setNote("J");
userMapper.findByUser(user).forEach(user1 -> System.out.println(user1));
}
}