1. MyBatis常用注解
这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写
Mapper映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。
@Insert:实现新增,代替了<insert></insert>
@Delete:实现删除,代替了<delete></delete>
@Update:实现更新,代替了<update></update>
@Select:实现查询,代替了<select></select>
@Result:实现结果集封装,代替了<result></result>
@Results:可以与@Result 一起使用,封装多个结果集,代替了<resultMap></resultMap>
@One:实现一对一结果集封装,代替了<association></association>
@Many:实现一对多结果集封装,代替了<collection></collection>
2. MyBatis注解的增删改查【重点】
2.1 创建UserMapper接口
package com.lagou.mapper;
import com.lagou.domain.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
@CacheNamespace // 配置了二级缓存
public interface UserMapper {
/*
查询用户
*/
@Select("select * from user")
public List<User> findAll();
/*
添加用户
*/
@Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
public void save(User user);
/*
更新用户
*/
@Update("update user set username = #{username},birthday=#{birthday} where id = #{id}")
public void update(User user);
/*
删除用户
*/
@Delete("delete from user where id = #{id}")
public void delete(Integer id);
/*
根据id查询用户
*/
@Select("select * from user where id = #{uid}")
public User findById(Integer uid);
/*
查询所有用户,及关联的订单信息
*/
@Select("select * from user")
@Results({
@Result(property = "id",column = "id",id = true),
@Result(property = "username",column = "username"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "ordersList",javaType = List.class,column = "id",many = @Many(select = "com.lagou.mapper.OrderMapper.findOrderByUid",fetchType = FetchType.LAZY))
})
public List<User> findAllWithOrder();
/*
查询所有用户及关联的角色信息
*/
@Select("select * from user")
@Results({
@Result(property = "id",column = "id",id = true),
@Result(property = "username",column = "username"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "roleList",javaType = List.class,column = "id",many = @Many(select = "com.lagou.mapper.RoleMapper.findAllByUid")),
})
public List<User> findAllWithRole();
}
2.2 编写核心配置文件
<!--我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可-->
<mappers>
<!--扫描使用注解的Mapper类-->
<mapper class="com.lagou.mapper.UserMapper"></mapper>
</mappers>
<!--或者指定扫描包含映射关系的接口所在的包也可以-->
<mappers>
<!--扫描使用注解的Mapper类所在的包-->
<package name="com.lagou.mapper"></package>
</mappers>
2.3 测试代码
public class TestUser extends TestBaseMapper {
// 查询
@Test
public void testFindAll() throws Exception {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> list = userMapper.findAll();
for (User user : list) { System.out.println(user);
}
}
// 添加
@Test
public void testSave() throws Exception {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User();
user.setUsername("于谦");
user.setBirthday(new Date()); user.setSex(" 男 "); user.setAddress("北京德云社"); userMapper.save(user);
}
// 更新
@Test
public void testUpdate() throws Exception {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User();
user.setId(49); user.setUsername("郭德纲"); user.setBirthday(new Date()); user.setSex("男");
user.setAddress("北京德云社");
userMapper.update(user);
}
// 删除
@Test
public void testDelete() throws Exception {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.delete(49);
}
}
3. 使用注解实现复杂映射开发
之前我们在映射文件中通过配置<resultMap>、<association>、<collection> 来实现复杂关系映射。
使用注解开发后,我们可以使用@Results、@Result,@One、@Many 注解组合完成复杂关系的配置。
4. 一对一查询
4.1 介绍
需求:查询一个订单,与此同时查询出该订单所属的用户
一对一查询语句
SELECT * FROM orders;
SELECT * FROM `user` WHERE id = #{订单的uid};
4.2 代码实现
1)OrderMapper接口
package com.lagou.mapper;
import com.lagou.domain.Orders;
import com.lagou.domain.User;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface OrderMapper {
/*
查询所有订单,同时查询订单所属的用户信息
*/
@Select("select * from orders")
@Results({ // 代替的就是resultMap标签 id标签 result标签
@Result(property = "id",column = "id",id = true),
@Result(property = "ordertime",column = "ordertime"),
@Result(property = "total",column = "total"),
@Result(property = "uid",column = "uid"),
@Result(property = "user",javaType = User.class,column = "uid",one = @One(select = "com.lagou.mapper.UserMapper.findById",fetchType = FetchType.EAGER))
})
public List<Orders> findAllWithUser();
}
2)UserMapper接口
package com.lagou.mapper;
import com.lagou.domain.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
@CacheNamespace // 配置了二级缓存
public interface UserMapper {
/*
根据id查询用户
*/
@Select("select * from user where id = #{uid}")
public User findById(Integer uid);
}
3)测试代码
package com.lagou.test;
import com.lagou.domain.Orders;
import com.lagou.domain.User;
import com.lagou.mapper.OrderMapper;
import com.lagou.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
// 在 @Test方法标注的方法执行之前来执行
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
/*
一对一查询(注解方式)
*/
@Test
public void testOneToOne(){
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List<Orders> allWithUser = mapper.findAllWithUser();
for (Orders orders : allWithUser) {
System.out.println(orders);
}
}
}
5. 一对多查询
5.1 介绍
需求:查询一个用户,与此同时查询出该用户具有的订单
一对多查询语句
SELECT * FROM `user`;
SELECT * FROM orders where uid = #{用户id};
5.2 代码实现
1)UserMapper接口
package com.lagou.mapper;
import com.lagou.domain.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
@CacheNamespace // 配置了二级缓存
public interface UserMapper {
/*
查询所有用户,及关联的订单信息
*/
@Select("select * from user")
@Results({
@Result(property = "id",column = "id",id = true),
@Result(property = "username",column = "username"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "ordersList",javaType = List.class,column = "id",many = @Many(select = "com.lagou.mapper.OrderMapper.findOrderByUid",fetchType = FetchType.LAZY))
})
public List<User> findAllWithOrder();
}
2)OrderMapper接口
package com.lagou.mapper;
import com.lagou.domain.Orders;
import com.lagou.domain.User;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface OrderMapper {
/*
根据传递过来的用户id,查询该用户所具有的订单信息
*/
@Select("select * from orders where uid = #{uid}")
public List<Orders> findOrderByUid(Integer uid);
}
3)测试代码
package com.lagou.test;
import com.lagou.domain.Orders;
import com.lagou.domain.User;
import com.lagou.mapper.OrderMapper;
import com.lagou.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
// 在 @Test方法标注的方法执行之前来执行
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
/*
一对多查询(注解方式)
*/
@Test
public void testOneToMany(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allWithOrder = mapper.findAllWithOrder();
for (User user : allWithOrder) {
System.out.println(user);
System.out.println(user.getOrdersList());
}
}
}
6. 多对多查询
6.1 介绍
需求:查询所有用户,同时查询出该用户的所有角色
多对多查询语句
SELECT * FROM `user`;
SELECT * FROM role r INNER JOIN user_role ur ON r.`id` = ur.`rid` WHERE ur.`uid` = #{用户id};
6.2 代码实现
1)UserMapper接口
package com.lagou.mapper;
import com.lagou.domain.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
@CacheNamespace // 配置了二级缓存
public interface UserMapper {
/*
查询所有用户及关联的角色信息
*/
@Select("select * from user")
@Results({
@Result(property = "id",column = "id",id = true),
@Result(property = "username",column = "username"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "roleList",javaType = List.class,column = "id",many = @Many(select = "com.lagou.mapper.RoleMapper.findAllByUid")),
})
public List<User> findAllWithRole();
}
2)RoleMapper接口
package com.lagou.mapper;
import com.lagou.domain.Role;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface RoleMapper {
/*
根据传递过来的用户id,查询该用户所具有的角色信息
*/
@Select("SELECT * FROM sys_role r INNER JOIN sys_user_role ur ON ur.roleid = r.id WHERE ur.userid = #{uid}")
public List<Role> findAllByUid(Integer uid);
}
3) 测试代码
package com.lagou.test;
import com.lagou.domain.Orders;
import com.lagou.domain.User;
import com.lagou.mapper.OrderMapper;
import com.lagou.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
// 在 @Test方法标注的方法执行之前来执行
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
}
@After
public void after(){
sqlSession.commit();
sqlSession.close();
}
多对多查询(注解方式)
*/
@Test
public void testManyToMany(){
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allWithRole = mapper.findAllWithRole();
for (User user : allWithRole) {
System.out.println(user);
System.out.println(user.getRoleList());
}
}
}
7. 基于注解的二级缓存
7.1 配置SqlMapConfig.xml文件开启二级缓存的支持
<settings>
<!--
因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。 为true代表开启二级缓存;为false代表不开启二级缓存。
-->
<setting name="cacheEnabled" value="true"/>
</settings>
7.2 在Mapper接口中使用注解配置二级缓存
@CacheNamespace
public interface UserMapper {...}
8. 注解延迟加载
不管是一对一还是一对多 ,在注解配置中都有fetchType的属性
9. 小结
节选自拉钩教育JAVA培训系列课程