《Mybatis使用手册》(第5篇 / 共5篇,持续更新),收藏 + 关注 不迷路,希望对小伙伴们有所帮助哦~
源码链接在文末 ↓ ↓ ↓
使用注解开发,可以减少Mapper映射文件的编写。
1、Mybatis常用注解
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用
2、使用注解实现基本CRUD
2.1、主配置文件
<configuration>
<!-- 引入外部配置文件 -->
<properties resource="jdbc.properties"/>
<!-- 实体类别名配置 -->
<typeAliases>
<package name="com.junlong.domain"/>
</typeAliases>
<!-- 环境配置 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<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>
<!-- 持久层接口配置 -->
<mappers>
<package name="com.junlong.dao"/>
</mappers>
</configuration>
2.2、持久层接口(注解开发)
public interface UserDao {
/**
* 查询所有用户
*
* @return 返回所有用户列表 List<User>
*/
@Select("select * from user")
@Results(
id = "userMap",
value = {
@Result(id = true, column = "id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"),
@Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress")
}
)
List<User> findAll();
/**
* 根据用户id查询用户信息
*
* @param id 用户id
* @return 返回用户对象 User
*/
@Select("select * from user where id = #{id}")
@ResultMap("userMap")
User findById(int id);
/**
* 新增用户
*
* @param user 用户对象
*/
@Insert("insert into user (username, birthday, sex, address) VALUES (#{userName}, #{userBirthday}, #{userSex}, #{userAddress})")
@SelectKey(keyColumn = "id", keyProperty = "userId", resultType = Integer.class, before = false, statement = "select last_insert_id()")
void saveUser(User user);
/**
* 更新用户信息
*
* @param user 用户对象
*/
@Update("update user set username = #{userName}, address = #{userAddress}, birthday = #{userBirthday}, sex = #{userSex} where id = #{userId}")
void updateUser(User user);
/**
* 根据用户id删除用户(物理删除)
*
* @param id 用户id
*/
@Delete("delete from user where id = #{id}")
void deleteUser(Integer id);
/**
* 聚合函数查询总记录数
*
* @return 返回总记录数
*/
@Select("select count(*) from user")
int findTotal();
/**
* 根据用户名模糊查询
*
* @param name 用户名(带 %)
* @return 返回符合条件的用户列表
*/
@Select("select * from user where username like #{username}")
@ResultMap("userMap")
List<User> findByName(String name);
}
2.3、测试
public class UserTest {
private InputStream inputStream;
private SqlSession sqlSession;
private UserDao userDao;
@Before
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
/**
* 测试查询所有用户
*/
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
/**
* 测试根据用户id查询用户
*/
@Test
public void testFindById() {
User user = userDao.findById(51);
System.out.println(user);
}
/**
* 测试新增用户
*/
@Test
public void testSaveUser() {
User user = new User();
user.setUserName("new user");
user.setUserBirthday(new Date());
user.setUserSex("女");
user.setUserAddress("阿尔及利亚");
System.out.println("保存前:" + user);
userDao.saveUser(user);
System.out.println("保存后:" + user);
}
/**
* 测试更新用户信息
*/
@Test
public void testUpdateUser() {
User user = userDao.findById(51);
user.setUserName("updateUser");
user.setUserAddress("刚果金");
userDao.updateUser(user);
}
/**
* 测试删除用户
*/
@Test
public void testDeleteUser() {
userDao.deleteUser(50);
}
/**
* 测试查询总记录数(聚合函数查询)
*/
@Test
public void testFindTotal() {
int total = userDao.findTotal();
System.out.println("共 " + total + " 条记录");
}
/**
* 测试根据用户名模糊查询
*/
@Test
public void testFindByName() {
List<User> users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
}
3、使用注解实现复杂映射关系
3.1、复杂映射关系注解
3.2、一对一复杂映射关系
3.2.1、账户及用户实体类
- 账户实体类
public class Account implements Serializable {
private int id; // 账户id
private int uid; // 用户id
private double money;
private User user; // 账户对应的用户对象
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}
- 用户实体类
public class User implements Serializable {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
3.2.2、账户及用户持久层接口(注解开发)
- 账户持久层接口
public interface AccountDao {
/**
* 查询所有账户,包含账户对应的用户信息(延迟加载)
*
* @return 返回所有账户列表
*/
@Select("select * from account")
@Results(
id = "accountMap",
value = {
@Result(id = true, column = "id", property = "id"),
@Result(column = "uid", property = "uid"),
@Result(column = "money", property = "money"),
@Result(column = "uid",
property = "user",
one = @One(select = "com.junlong.dao.UserDao.findById", fetchType = FetchType.LAZY)
)
}
)
List<Account> findAll();
}
- 用户持久层接口
public interface UserDao {
/**
* 根据用户id查询用户
*
* @param id 用户id
* @return 返回用户对象
*/
@Select("select * from user where id = #{id}")
User findById(Integer id);
}
3.2.3、测试
public class AccountTest {
private InputStream inputStream;
private SqlSession sqlSession;
private AccountDao accountDao;
@Before
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
accountDao = sqlSession.getMapper(AccountDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
/**
* 测试查询所有账户
*/
@Test
public void testFindAll() {
List<Account> accounts = accountDao.findAll();
for (Account account : accounts) {
System.out.println(account.getMoney());
}
}
}
如运行结果所示,注解种使用了延迟加载,没有使用户相关的信息,因此并没有执行查询用户信息的SQL。
3.3、一对多复杂映射关系
3.3.1、账户及用户实体类
- 账户实体类
public class Account implements Serializable {
private int id; // 账户id
private int uid; // 用户id
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
- 用户实体类
public class User implements Serializable {
private int id; // 用户id
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", accounts=" + accounts +
'}';
}
}
3.3.2、账户及用户持久层接口
- 账户持久层接口
public interface AccountDao {
/**
* 根据用户uid查询所有账户
*
* @param uid 用户id
* @return 返回该用户id的所有账户列表
*/
@Select("select * from account where uid = #{uid}")
List<Account> findByUid(int uid);
}
- 用户持久层接口
public interface UserDao {
/**
* 查询所有用户,包含用户的所有账户信息(延迟加载)
*
* @return 返回所有用户列表
*/
@Select("select * from user")
@Results(
id = "userMap",
value = {
@Result(id = true, column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "birthday", property = "birthday"),
@Result(column = "sex", property = "sex"),
@Result(column = "address", property = "address"),
@Result(column = "id",
property = "accounts",
many = @Many(select = "com.junlong.dao.AccountDao.findByUid", fetchType = FetchType.LAZY)
)
}
)
List<User> findAll();
}
3.3.3、测试
public class UserTest {
private InputStream inputStream;
private SqlSession sqlSession;
private UserDao userDao;
@Before
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
userDao = sqlSession.getMapper(UserDao.class);
}
@After
public void destroy() throws IOException {
sqlSession.commit();
sqlSession.close();
inputStream.close();
}
/**
* 测试查询所有用户(包含该用户的所有账户信息)
*/
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user.getUsername());
}
}
}
如运行结果所示,注解配置了延迟加载,由于没有使用账户相关信息,因此并没有执行查询账户信息的SQL。
4、基于注解的二级缓存
4.1、主配置文件
<configuration>
<!-- 外部配置文件 -->
<properties resource="jdbc.properties"/>
<!-- 开启二级缓存 -->
<settings>
<!-- cacheEnabled 默认取值为 true,可以省略不配 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 实体类别名 -->
<typeAliases>
<package name="com.junlong.domain"/>
</typeAliases>
<!-- 环境配置 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<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>
<!-- dao路径 -->
<mappers>
<package name="com.junlong.dao"/>
</mappers>
</configuration>
4.2、用户持久层接口开启二级缓存(注解开发)
// 配置二级缓存
@CacheNamespace(blocking = true)
public interface UserDao {
/**
* 根据用户id查询用户
*
* @param id 用户id
* @return 返回用户对象
*/
@Select("select * from user where id = #{id}")
User findById(Integer id);
}
4.3、测试
public class UserTest {
private InputStream inputStream;
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@After
public void destroy() throws IOException {
inputStream.close();
}
/**
* 测试根据用户id查询用户(二级缓存)
*
* 注意:只有当sqlSession被 提交 或 关闭 后,二级缓存才能生效
*/
@Test
public void testFindById() {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserDao userDao1 = sqlSession1.getMapper(UserDao.class);
User user1 = userDao1.findById(51);
System.out.println(user1);
sqlSession1.commit();
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
User user2 = userDao2.findById(51);
System.out.println(user2);
sqlSession2.commit();
sqlSession2.close();
System.out.println(user1 == user2);
}
}
如运行结果所示,两次查询只执行了一次SQL,由于二级缓存使用的是序列化存储,所以两次查询得到的对象并不是用一个。
3、源码下载
源码下载链接