MyBatis —— 第三十二章 MyBatis 注解开发
1. MyBatis 的常用注解
近几年来注解开发越来越流行,MyBatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射文件了。我们先围绕一些基本的 CRUD 操作来学习,在学习复杂的多映射操作
@Insert
: 实现新增@Update
: 实现更新@Delete
: 实现删除@Select
: 实现查询@Result
: 实现结果封装@Results
: 可以与@Result
一起使用,封装多个结果集@One
: 实现一对一结果集封装@Many
: 实现一对多结果集封装
2. MyBatis 的增删改查
我们完成简单的 user
表的增删改查操作
sqlMapConfig.xml
<?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>
<!-- Load the external properties file through the properties tag -->
<properties resource="jdbc.properties"></properties>
<!-- Define alias -->
<typeAliases>
<typeAlias type="com.gregperlinli.domain.User" alias="user" />
</typeAliases>
<!-- Data source environment -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- Load mapping relationship -->
<mappers>
<!-- Specify the package where the interface is located -->
<package name="com.gregperlinli.mapper"/>
</mappers>
</configuration>
com.yourname.mapper.UserMapper
/**
* @author gregPerlinLi
* @since 2021-10-08
*/
public interface UserMapper {
/**
* save user
*
* @param user user to save
*/
@Insert(value = "insert into user values(#{id}, #{username}, #{password}, #{birthday})")
void save(User user);
/**
* Update user
*
* @param user user to update
*/
@Update(value = "update user set username = #{username}, password = #{password} where id = #{id}")
void update(User user);
/**
* Delete user
*
* @param id user id to delete
*/
@Delete(value = "delete from user where id = #{id}")
void delete(int id);
/**
* Find by id
*
* @param id id to find
* @return user
*/
@Select(value = "select * from user where id = #{id}")
User findById(int id);
/**
* Find all
* @return All users
*/
@Select(value = "select * from user")
List<User> findAll();
}
com.gregperlinli.test.MybatisTest
/**
* @author gregPerlinLi
* @since 2021-10-08
*/
public class MybatisTest {
private UserMapper userMapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void testSave() {
User user = new User();
user.setUsername("Tom");
user.setPassword("abc");
user.setId(10);
userMapper.save(user);
}
@Test
public void testUpdate() {
User user = new User();
user.setId(10);
user.setUsername("Lucy");
user.setPassword("123");
userMapper.update(user);
}
@Test
public void testDelete() {
userMapper.delete(10);
}
@Test
public void testFindById() {
User user = userMapper.findById(2);
System.out.println(user);
}
@Test
public void testFindAll() {
List<User> userList = userMapper.findAll();
userList.forEach(System.out::println);
}
}
3. MyBatis 的注解实现复杂映射开发
实现复杂关系映射之前我们可以在映射文件中配置 <resultMap>
来实现,使用注解开发后,我们可以使用 @Results
注解,@Result
注解,@One
注解,@Many
注解组合完成复杂关系的配置
注解 | 说明 |
---|---|
@Results |
代替的是标签 <resultMap> ,该注解中可以使用单个 @Result 注解,也可以使用 @Result 注解,也可以使用 @Result 集合。使用格式:@Results({@Result(), @Result()}) 或 @Results(@Result()) |
@Result |
代替了 <id> 标签和 <result> 标签@Result 中属性介绍:column :数据库的列名property :需要装配的属性名one :需要使用的 @One 注解(@Result(one = @One) )many :需要使用的 @Many 注解(@Result(many = @Many) ) |
@One |
代替了 <assocation> 标签,是夺标查询的关键,在注解中用来指定子查询返回单一对象。@One 注解属性介绍:select :指定用来多表查询的 sqlmapper 使用格式: @Result(column = "", property = "", one = @One(select = "")) |
@Many |
代替了 <collection> 标签,是多表查询的关键,在注解中用来指定查询返回对象集合。使用格式: @Result(property = "", column = "", many = @Many(select = "")) |
4. 一对一查询
4.1. 一对一查询的模型
用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求: 查询一个订单,与此同时查询出该订单的所属用户
4.2. 示例代码
com.yourname.mapper.OrderMapper
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public interface OrderMapper {
/**
* Find all order
* @return Order list
*/
@Select(value = "select * from orders")
@Results(value = {
@Result(column = "id", property = "id"),
@Result(column = "order_time", property = "orderTime"),
@Result(column = "total", property = "total"),
@Result(
property = "user", // The name of the property to encapsulate
column = "uid", // According to which field to query the data of the user table
javaType = User.class, // Entity type to encapsulate
// The select property represents the method used to query which interface to obtain data
one = @One(select = "com.gregperlinli.mapper.UserMapper.findById")
)
})
List<Order> findAll();
}
com.yourname.test.MybatisTest
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public class MybatisTest {
private OrderMapper orderMapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
orderMapper = sqlSession.getMapper(OrderMapper.class);
}
@Test
public void testFindAll() {
List<Order> userList = orderMapper.findAll();
userList.forEach(System.out::println);
}
}
5. 一对多查询
5.1. 一对多查询的模型
用户表和订单的关系为:一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求: 查询一个用户,与此同时查询出该用户具有的订单
5.2. 示例代码
com.yourname.domain.Order
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public class Order {
private int id;
private Date orderTime;
private double total;
private int uid;
/**
* Which user does the current order belong to
*/
private User user;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getOrderTime() {
return orderTime;
}
public void setOrderTime(Date orderTime) {
this.orderTime = orderTime;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Order{" +
"id=" + id +
", orderTime=" + orderTime +
", total=" + total +
", uid=" + uid +
", user=" + user +
'}';
}
}
com.yourname.mapper.UserMapper
/**
* @author gregPerlinLi
* @since 2021-10-08
*/
public interface UserMapper {
/**
* Find all user and order
*
* @return All user with order
*/
@Select("select * from user")
@Results(value = {
@Result(id = true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(
property = "orderList",
column = "id",
javaType = List.class, // What needs to be returned here is a List, not an Order
many = @Many(select = "com.gregperlinli.mapper.OrderMapper.findByUid")
)
})
List<User> findUserAndOrder();
}
com.yourname.mapper.OrderMapper
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public interface OrderMapper {
/**
* Find order by uid
* @param uid uid to find
* @return Order list
*/
@Select(value = "select * from orders where uid = #{uid}")
public List<Order> findByUid(int uid);
}
com.yourname.test.MybatisTest
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public class MybatisTest {
private UserMapper userMapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void testFindAll() {
List<User> userList = userMapper.findUserAndOrder();
userList.forEach(System.out::println);
}
}
6. 多对多查询
6.1. 多对多查询的模型
用户表和角色表的关系为:一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求: 查询用户同时查询出该用户的所有角色
6.2. 示例代码
com.yourname.domain.User
/**
* @author gregPerlinLi
* @since 2021-10-08
*/
public class User {
private int id;
private String username;
private String password;
/**
* What roles does the current user have
*/
private List<Role> roleList;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Order> getOrderList() {
return orderList;
}
public void setOrderList(List<Order> orderList) {
this.orderList = orderList;
}
public List<Role> getRoleList() {
return roleList;
}
public void setRoleList(List<Role> roleList) {
this.roleList = roleList;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", roleList=" + roleList +
'}';
}
}
com.yourname.domain.Role
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public class Role {
private int id;
private String roleName;
private String roleDesc;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
com.yourname.mapper.RoleMapper
/**
* @author gregPerlinLi
* @since 2021-10-13
*/
public interface RoleMapper {
/**
* Find role by user id
*
* @param uid user id to find
* @return role list by user id
*/
@Select(value = "select * from user_role ur, role r where ur.role_id = r.id and ur.user_id = #{uid}")
List<Role> findByUid(int uid);
}
com.yourname.mapper.UserMapeer
/**
* @author gregPerlinLi
* @since 2021-10-08
*/
public interface UserMapper {
/**
* Find all user with roles
*
* @return User list with roles
*/
@Select(value = "select * from user")
@Results(value = {
@Result(id = true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many = @Many(select = "com.gregperlinli.mapper.RoleMapper.findByUid")
)
})
List<User> findUserAndRoleAll();
}