Mybatis 注解开发

朱雀 2021-06-10 20:37 632阅读 0赞

这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射 文件了。本次我们先围绕一些基本的 CRUD 来学习,再学习复杂映射关系及延迟加载。

3.1 mybatis 的常用注解说明

  1. @Insert:实现新增
  2. @Update:实现更新
  3. @Delete:实现删除
  4. @Select:实现查询
  5. @Result:实现结果集封装
  6. @Results:可以与@Result 一起使用,封装多个结果集
  7. @ResultMap:实现引用@Results 定义的封装
  8. @One:实现一对一结果集封装
  9. @Many:实现一对多结果集封装
  10. @SelectProvider: 实现动态 SQL 映射
  11. @CacheNamespace:实现注解二级缓存的使用

3.2 使用 Mybatis 注解实现基本 CRUD

单表的 CRUD 操作是最基本的操作,前面我们的学习都是基于 Mybaits 的映射文件来实现的。

3.2.1 编写实体类

  1. package com.itheima.domain;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. /**
  5. * @author 黑马程序员
  6. * @Company http://www.ithiema.com
  7. */
  8. public class User implements Serializable{
  9. private Integer id;
  10. private String username;
  11. private String address;
  12. private String sex;
  13. private Date birthday;
  14. public Integer getId() {
  15. return id;
  16. }
  17. public void setId(Integer id) {
  18. this.id = id;
  19. }
  20. public String getUsername() {
  21. return username;
  22. }
  23. public void setUsername(String username) {
  24. this.username = username;
  25. }
  26. public String getAddress() {
  27. return address;
  28. }
  29. public void setAddress(String address) {
  30. this.address = address;
  31. }
  32. public String getSex() {
  33. return sex;
  34. }
  35. public void setSex(String sex) {
  36. this.sex = sex;
  37. }
  38. public Date getBirthday() {
  39. return birthday;
  40. }
  41. public void setBirthday(Date birthday) {
  42. this.birthday = birthday;
  43. }
  44. @Override
  45. public String toString() {
  46. return "User{" +
  47. "id=" + id +
  48. ", username='" + username + '\'' +
  49. ", address='" + address + '\'' +
  50. ", sex='" + sex + '\'' +
  51. ", birthday=" + birthday +
  52. '}';
  53. }
  54. }

注意: 此处我们故意和数据库表的列名不一致。

3.2.2 使用注解方式开发持久层接口

3.2.2 使用注解方式开发持久层接口

format_png

完整的DAO类

  1. public interface IUserDao {
  2. /**
  3. * 查询所有用户
  4. * @return
  5. */
  6. @Select("select * from user")
  7. List<User> findAll();
  8. /**
  9. * 保存用户
  10. * @param user
  11. */
  12. @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
  13. void saveUser(User user);
  14. /**
  15. * 更新用户
  16. * @param user
  17. */
  18. @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
  19. void updateUser(User user);
  20. /**
  21. * 删除用户
  22. * @param userId
  23. */
  24. @Delete("delete from user where id=#{id} ")
  25. void deleteUser(Integer userId);
  26. /**
  27. * 根据id查询用户
  28. * @param userId
  29. * @return
  30. */
  31. @Select("select * from user where id=#{id} ")
  32. User findById(Integer userId);
  33. /**
  34. * 根据用户名称模糊查询
  35. * @param username
  36. * @return
  37. */
  38. // @Select("select * from user where username like #{username} ")
  39. @Select("select * from user where username like '%${value}%' ")
  40. List<User> findUserByName(String username);
  41. /**
  42. * 查询总用户数量
  43. * @return
  44. */
  45. @Select("select count(*) from user ")
  46. int findTotalUser();
  47. }

3.2.3 编写 SqlMapConfig 配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <!-- 引入外部配置文件-->
  7. <properties resource="jdbcConfig.properties"></properties>
  8. <!--配置别名-->
  9. <typeAliases>
  10. <package name="com.itheima.domain"></package>
  11. </typeAliases>
  12. <!-- 配置环境-->
  13. <environments default="mysql">
  14. <environment id="mysql">
  15. <transactionManager type="JDBC"></transactionManager>
  16. <dataSource type="POOLED">
  17. <property name="driver" value="${jdbc.driver}"></property>
  18. <property name="url" value="${jdbc.url}"></property>
  19. <property name="username" value="${jdbc.username}"></property>
  20. <property name="password" value="${jdbc.password}"></property>
  21. </dataSource>
  22. </environment>
  23. </environments>
  24. <!-- 指定带有注解的dao接口所在位置 -->
  25. <mappers>
  26. <mapper class="com.itheima.dao.IUserDao"></mapper>
  27. </mappers>
  28. </configuration>

format_png 1

3.2.4 编写测试方法

  1. @Test
  2. public void testSave(){
  3. User user = new User();
  4. user.setUsername("mybatis annotation");
  5. user.setAddress("北京市昌平区");
  6. userDao.saveUser(user);
  7. }
  8. @Test
  9. public void testUpdate(){
  10. User user = new User();
  11. user.setId(57);
  12. user.setUsername("mybatis annotation update");
  13. user.setAddress("北京市海淀区");
  14. user.setSex("男");
  15. user.setBirthday(new Date());
  16. userDao.updateUser(user);
  17. }
  18. @Test
  19. public void testDelete(){
  20. userDao.deleteUser(51);
  21. }
  22. @Test
  23. public void testFindOne(){
  24. User user = userDao.findById(57);
  25. System.out.println(user);
  26. }
  27. @Test
  28. public void testFindByName(){
  29. // List<User> users = userDao.findUserByName("%mybatis%");
  30. List<User> users = userDao.findUserByName("mybatis");
  31. for(User user : users){
  32. System.out.println(user);
  33. }
  34. }
  35. @Test
  36. public void testFindTotal(){
  37. int total = userDao.findTotalUser();
  38. System.out.println(total);
  39. }

3.3 使用注解实现复杂关系映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置来实现,在使用注解开发时我们需要借 助@Results 注解,@Result 注解,@One 注解,@Many 注解。

3.3.1 复杂关系映射的注解说明

  1. @Results 注解 代替的是标签<resultMap> 该注解中可以使用单个@Result 注解,也可以使用@Result 集合 @Results({@Result(),@Result()})或@Results@Result())
  2. @Resutl 注解 代替了 <id>标签和<result>标签
  3. @Result 属性介绍:
  4. id 是否是主键字段 column 数据库的列名 property 需要装配的属性名 one 需要使用的@One 注解(@Resultone=@One)())) many 需要使用的@Many 注解(@Resultmany=@many)()))
  5. @One 注解(一对一) 代替了<assocation>标签,是多表查询的关键,
  6. 在注解中用来指定子查询返回单一对象。
  7. @One 注解属性介绍: select 指定用来多表查询的 sqlmapper fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。 使用格式: @Result(column=" ",property="",one=@One(select=""))
  8. @Many 注解(多对一) 代替了<Collection>标签,是是多表查询的关键,
  9. 在注解中用来指定子查询返回对象集合。
  10. 注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,
  11. 属性的 javaType (一般为 ArrayList)但是注解中可以不定义;
  12. 使用格式: @Result(property="",column="",many=@Many(select=""))

3.3.2 使用注解实现一对一复杂关系映射及延迟加载

需求: 加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载。(注解方式实现)

3.3.2.1 添加 User 实体类及 Account 实体类

  1. public class User implements Serializable{
  2. private Integer userId;
  3. private String userName;
  4. private String userAddress;
  5. private String userSex;
  6. private Date userBirthday;
  7. //一对多关系映射:一个用户对应多个账户
  8. private List<Account> accounts;
  9. public List<Account> getAccounts() {
  10. return accounts;
  11. }
  12. public void setAccounts(List<Account> accounts) {
  13. this.accounts = accounts;
  14. }
  15. public Integer getUserId() {
  16. return userId;
  17. }
  18. public void setUserId(Integer userId) {
  19. this.userId = userId;
  20. }
  21. public String getUserName() {
  22. return userName;
  23. }
  24. public void setUserName(String userName) {
  25. this.userName = userName;
  26. }
  27. public String getUserAddress() {
  28. return userAddress;
  29. }
  30. public void setUserAddress(String userAddress) {
  31. this.userAddress = userAddress;
  32. }
  33. public String getUserSex() {
  34. return userSex;
  35. }
  36. public void setUserSex(String userSex) {
  37. this.userSex = userSex;
  38. }
  39. public Date getUserBirthday() {
  40. return userBirthday;
  41. }
  42. public void setUserBirthday(Date userBirthday) {
  43. this.userBirthday = userBirthday;
  44. }
  45. @Override
  46. public String toString() {
  47. return "User{" +
  48. "userId=" + userId +
  49. ", userName='" + userName + '\'' +
  50. ", userAddress='" + userAddress + '\'' +
  51. ", userSex='" + userSex + '\'' +
  52. ", userBirthday=" + userBirthday +
  53. '}';
  54. }
  55. }
  56. public class Account implements Serializable {
  57. private Integer id;
  58. private Integer uid;
  59. private Double money;
  60. //多对一(mybatis中称之为一对一)的映射:一个账户只能属于一个用户
  61. private User user;
  62. public User getUser() {
  63. return user;
  64. }
  65. public void setUser(User user) {
  66. this.user = user;
  67. }
  68. public Integer getId() {
  69. return id;
  70. }
  71. public void setId(Integer id) {
  72. this.id = id;
  73. }
  74. public Integer getUid() {
  75. return uid;
  76. }
  77. public void setUid(Integer uid) {
  78. this.uid = uid;
  79. }
  80. public Double getMoney() {
  81. return money;
  82. }
  83. public void setMoney(Double money) {
  84. this.money = money;
  85. }
  86. @Override
  87. public String toString() {
  88. return "Account{" +
  89. "id=" + id +
  90. ", uid=" + uid +
  91. ", money=" + money +
  92. '}';
  93. }
  94. }

3.3.2.2 添加账户的持久层接口并使用注解配置

  1. public interface IAccountDao {
  2. /**
  3. * 查询所有账户,并且获取每个账户所属的用户信息
  4. * @return
  5. */
  6. @Select("select * from account")
  7. @Results(id="accountMap",value = {
  8. @Result(id=true,column = "id",property = "id"),
  9. @Result(column = "uid",property = "uid"),
  10. @Result(column = "money",property = "money"),
  11. @Result(property = "user",column = "uid",one=@One(select="com.itheima.dao.IUserDao.findById",fetchType= FetchType.EAGER))
  12. })
  13. List<Account> findAll();
  14. /**
  15. * 根据用户id查询账户信息
  16. * @param userId
  17. * @return
  18. */
  19. @Select("select * from account where uid = #{userId}")
  20. List<Account> findAccountByUid(Integer userId);
  21. }

3.3.2.3 添加用户的持久层接口并使用注解配置

  1. @CacheNamespace(blocking = true)
  2. public interface IUserDao {
  3. /**
  4. * 查询所有用户
  5. * @return
  6. */
  7. @Select("select * from user")
  8. @Results(id="userMap",value={
  9. @Result(id=true,column = "id",property = "userId"),
  10. @Result(column = "username",property = "userName"),
  11. @Result(column = "address",property = "userAddress"),
  12. @Result(column = "sex",property = "userSex"),
  13. @Result(column = "birthday",property = "userBirthday"),
  14. @Result(property = "accounts",column = "id",
  15. many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
  16. fetchType = FetchType.LAZY))
  17. })
  18. List<User> findAll();
  19. /**
  20. * 根据id查询用户
  21. * @param userId
  22. * @return
  23. */
  24. @Select("select * from user where id=#{id} ")
  25. @ResultMap("userMap")
  26. User findById(Integer userId);
  27. /**
  28. * 根据用户名称模糊查询
  29. * @param username
  30. * @return
  31. */
  32. @Select("select * from user where username like #{username} ")
  33. @ResultMap("userMap")
  34. List<User> findUserByName(String username);
  35. }

3.3.2.4 测试一对一关联及延迟加载

  1. @Test
  2. public void testFindAll(){
  3. List<Account> accounts = accountDao.findAll();
  4. /*
  5. for(Account account : accounts){
  6. System.out.println("----每个账户的信息-----");
  7. System.out.println(account);
  8. System.out.println(account.getUser());
  9. }
  10. */
  11. }

3.3.3 使用注解实现一对多复杂关系映射

需求: 查询用户信息时,也要查询他的账户列表。使用注解方式实现。 分析: 一个用户具有多个账户信息,所以形成了用户(User)与账户(Account)之间的一对多关系。

3.3.3.1 User 实体类加入 List

  1. //一对多关系映射:一个用户对应多个账户
  2. private List<Account> accounts;
  3. public List<Account> getAccounts() {
  4. return accounts;
  5. }
  6. public void setAccounts(List<Account> accounts) {
  7. this.accounts = accounts;
  8. }

3.3.3.2 编写用户的持久层接口并使用注解配置

  1. @CacheNamespace(blocking = true)
  2. public interface IUserDao {
  3. /**
  4. * 查询所有用户
  5. * @return
  6. */
  7. @Select("select * from user")
  8. @Results(id="userMap",value={
  9. @Result(id=true,column = "id",property = "userId"),
  10. @Result(column = "username",property = "userName"),
  11. @Result(column = "address",property = "userAddress"),
  12. @Result(column = "sex",property = "userSex"),
  13. @Result(column = "birthday",property = "userBirthday"),
  14. @Result(property = "accounts",column = "id",
  15. many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
  16. fetchType = FetchType.LAZY))
  17. })
  18. List<User> findAll();
  19. /**
  20. * 根据id查询用户
  21. * @param userId
  22. * @return
  23. */
  24. @Select("select * from user where id=#{id} ")
  25. @ResultMap("userMap")
  26. User findById(Integer userId);
  27. /**
  28. * 根据用户名称模糊查询
  29. * @param username
  30. * @return
  31. */
  32. @Select("select * from user where username like #{username} ")
  33. @ResultMap("userMap")
  34. List<User> findUserByName(String username);
  35. }
  36. @Many:
  37. 相当于<collection>的配置 select 属性:代表将要执行的 sql 语句
  38. fetchType 属性:代表加载方式,一般如果要延迟加载都设置为 LAZY 的值

3.3.3.3 编写账户的持久层接口并使用注解配置

  1. /**
  2. * 根据用户id查询账户信息
  3. * @param userId
  4. * @return
  5. */
  6. @Select("select * from account where uid = #{userId}")
  7. List<Account> findAccountByUid(Integer userId);

3.3.3.4 添加测试方法

  1. /**
  2. * 测试查询所有 */
  3. @Test public void testFindAll() {
  4. List<User> users = userDao.findAll(); //
  5. for(User user : users) {
  6. System.out.println("-----每个用户的内容-----");
  7. System.out.println(user); //
  8. System.out.println(user.getAccounts()); // }
  9. }

3.4 mybatis 基于注解的二级缓存

3.4.1 在 SqlMapConfig 中开启二级缓存支持

  1. <!-- 配置二级缓存 -->
  2. <settings>
  3. <!-- 开启二级缓存的支持 -->
  4. <setting name="cacheEnabled" value="true"/>
  5. </settings>

3.4.2 在持久层接口中使用注解配置二级缓存

format_png 2

发表评论

表情:
评论列表 (有 0 条评论,632人围观)

还没有评论,来说两句吧...

相关阅读

    相关 MyBatis注解开发

    除了XML映射方式,MyBatis还支持注解方式实现POJO对象和数据表之间的关联映射,使用注解的方式一般将SQL语句直接写到接口上。与XML的映射方式相比,基于注解的映射方式

    相关 Mybatis 注解开发

    这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射 文件了。本次我们先围绕一些基本的 CRUD 来学习,再学习复杂映