乐鱼电竞

    教育行业A股IPO第一股(股票代码 003032)

    全国咨询/投诉热线:400-618-4000

    Spring Boot中使用MyBatis注解配置详解

    更新时间:2018年09月21日17时27分 来源:乐鱼播客 浏览次数:

    1.0 之前在Spring Boot中整合MyBatis时,采用了注解的配置方式,相信很多人还是比较喜欢这种优雅的方式的,也遇到不少问题,主要集中于针对各种场景下注解如何使用,下面就对几种常见的情况举例说明用法。

    1.1 在做下面的示例之前,先准备一个整合好MyBatis的工程,可参见:使用Springboot整合mybatis

    2.0 传参方式

          下面通过几种不同传参方式来实现前文中实现的插入操作。

    2.1使用@Param

         使用这种最简单的传参方式,如下:

    [Java] 纯文本查看 复制代码
    ?
    1
    2
    @Insert("insert into book (bookname) values #{bookname}")
        Integer insertBook(@Param("bookname") String bookname);

    这种方式很好理解,@Param 中定义的 bookname 对应了SQL中的  #{bookname}。

    2.2 使用Map

    [Java] 纯文本查看 复制代码
    ?
    1
    2
    @Insert("insert into book (bookname) values #{bookname, jdbcType =VARCHAR}")
        Integer insertBookByMap(Map<String,Object> map );

    对于Insert语句中需要的参数,我们只需要在map中填入同名的内容即可,具体如下面代码所示:

    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    Map<String, Object> map = new HashMap<>();
           map.put("bookname", "CCC");
           bookDaoMapper.insertBookByMap(map);

    2.3 使用对象

    除了Map对象,我们也可直接使用普通的Java对象来作为查询条件的传参,比如我们可以直接使用Book对象:

    [Java] 纯文本查看 复制代码
    ?
    1
    2
    @Insert("insert into book (bookname) values #{bookname}")
        Integer insertBookByPo(Book book);

    3.0 增删改查

    3.1 MyBatis针对不同的数据库操作分别提供了不同的注解来进行配置,在之前的示例中演示了@Insert,下面针对User表做一组最基本的增删改查作为示例:

    [Java] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    public interface UserMapper {
            @Select("SELECT * FROM user WHERE name = #{name}")
            User findByName(@Param("name") String name);
            @Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
            int insert(@Param("name") String name, @Param("age") Integer age);
            @Update("UPDATE user SET age=#{age} WHERE name=#{name}")
            void update(User user);
            @Delete("DELETE FROM user WHERE id =#{id}")
            void delete(Long id);
        }

    在完成了一套增删改查后,单元测试来验证上面操作的正确性:省略。。。

    3.2 返回结果的绑定

           对于增、删、改操作相对变化较小。而对于“查”操作,我们往往需要进行多表关联,汇总计算等操作,那么对于查询的结果往往就不再是简单的实体对象了,往往需要返回一个与数据库实体不同的包装类,那么对于这类情况,就可以通过@Results和@Result注解来进行绑定,具体如下:      
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    6
    @Results({
        @Result(property = "name", column = "name"),
        @Result(property = "age", column = "age")
    })
    @Select("SELECT name, age FROM user")
    List<User> findAll();

        4.0 Mybatis注解进行一对多和多对多查询
          4.1模拟的业务查询

          系统中的用户user都有唯一对应的地址信息address,每个用户可以有多量车car,类似如下结构
          
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    |-- user
        |-- address
        |-- carList
            |-- car1
            |-- car2

          4.2 对应的实体类如下
          
    [Java] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //省略setter/getter
    public class Address {
        private Long id;
        private String province;
        private String city;
    }
    public class Car {
        private Long id;
        private String color;
        private String name;
        //用户id
        private Long userId;
    }
    public class User {
        private Long id;
        //地址信息,和用户是一对一的关系
        private Address address;
        //地址id
        private Long addressId;
        //用户拥有的车,和用户是一对多的关系
        private List<Car> cars;
    }
        4.3 对应的建表语句和模拟数据如下
       
    [SQL] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    CREATE TABLE IF NOT EXISTS `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `nick_name` varchar(50) DEFAULT NULL,
      `address_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    CREATE TABLE IF NOT EXISTS `address` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `province` varchar(50) DEFAULT NULL,
      `city` varchar(50) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    CREATE TABLE IF NOT EXISTS `car` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `color` varchar(50) DEFAULT NULL,
      `name` varchar(50) DEFAULT NULL,
      `user_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    INSERT INTO
        `user`
    VALUES
        ('1', 'baby', '1'),
        ('2', 'kingboy', '2'),
        ('3', 'boy', '3'),
        ('4', 'kingbaby', '4');
    INSERT INTO
        `address`
    VALUES
        ('1', '北京', '北京'),
        ('2', '天津', '天津'),
        ('3', '安徽', '宿州'),
        ('4', '广东', '广州');
    INSERT INTO
        `car`
    VALUES
        ('1', 'green', '路虎', '1'),
        ('2', 'white', '奔驰', '2'),
        ('3', 'blue', '玛莎拉蒂', '4'),
        ('4', 'yellow', '兰博基尼', '4');
      4.4 @One一对一映射
       4.4.1 以获取用户的唯一地址为例,首先我们定义一个根据地址id查询地址的查询方法
       
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    6
    7
    public interface AddressRepository {
        /**
         * 根据地址id查询地址
         */
        @Select("SELECT * FROM `address` WHERE id = #{id}")
        Address findAddressById(Long id);
    }
       4.4.2 然后我们定义一个根据用户id查询用户的方法
       
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    public interface UserRepository {
        @Select("SELECT * FROM `user` where id = #{id}")
        User findUserWithAddress(Long id);
    }
      4.4.3 这个时候我们查询出来的user对象中的address属性是空的,和address并没有任何关联。 
       那么我们要把user中的addressId传递给AddressRepository的查询地址的方法, 
       然后把查询出的地址对象address赋值给user的address属性,那么我们怎么做呢?
       
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    public interface UserRepository {
        @Select("SELECT * FROM `user` where id = #{id}")
        @Results({
                @Result(property = "address", column = "address_id",
                        one = @One(select = "com.kingboy.repository.address.AddressRepository.findAddressById"))
        })
        User findUserWithAddress(Long id);
    }
        4.4.5 我们要使用@Resutl注解对返回的结果进行配置, 
                - property = “address”, 表示要将返回的查询结果赋值给user的address属性 
                - column = “address_id” 是指将user表中的address_id作为com.kingboy.repository.address.AddressRepository.findAddressById的查询参数 
                - one 表示这是一个一对一的查询 
                - @One(select = “方法全路径) 表示我们调用的方法
        4.5 @Many一对多查询
        4.5.1 以获取用户拥有的所有车car为例,首先我们定义一个根据用户id查询车的查询方法

    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    6
    7
    public interface CarRepository {
        /**
         * 根据用户id查询所有的车
         */
        @Select("SELECT * FROM `car` WHERE user_id = #{userId}")
        List<Car> findCarByUserId(Long userId);
    }

        4.5.2 然后我们定义一个根据用户id查询用户的方法
       
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    public interface UserRepository {
        @Select("SELECT * FROM `user` where id = #{id}")
        User findUserWithAddress(Long id);
    }
        4.5.3 这个时候我们查询出来的user对象中的List属性是空的,和car的查询方法并没有任何关联。 
        那么我们要把user中的用户id传递给CarRepository的查询车的方法, 
        然后把查询出的集合对象List赋值给user的cars属性,那么我们怎么做呢?
       
    [Java] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    public interface UserRepository {
        /**
         * 查询带有车信息的用户===============演示一对多(关于多对多其实就是两个一对多组成)
         */
        @Select("SELECT * FROM `user` WHERE id = #{id}")
        @Results({
                @Result(property = "cars", column = "id",
                        many = @Many(select = "com.kingboy.repository.car.CarRepository.findCarByUserId"))
        })
        User getUserWithCar(Long id);
    }
        4.5.4 我们要使用@Resutl注解对返回的结果进行配置, 
                    - property = “cars”, 表示要将返回的查询结果赋值给user的cars属性 
                    - column = “id” 是指将user表中的用户主键id作为com.kingboy.repository.address.CarRepository.findCarByUserId的查询参数 
                    - many 表示这是一个一对多的查询 
                    - @Many(select = “方法全路径) 表示我们调用的方法, 方法参数userId就是上面column指定的列值
        5.0 @One @Many的总结
                    首先我们统一下概念:查询Address或Car的方法,接下来统称为User的附属查询。


                    共同点: 
                    - 无论是一对一还是一对多,都是通过附属查询来实现的,我们需要定义这个附属查询方法。 
                    - 在主查询方法中通过@One、@Many指定附属查询方法的全路径。 
                    - 都通过column来传递参数给附属方法。


                    不同点: 
                    - 一对一,那么附属方法返回的是一个单独的对象 
                    - 一对多,那么附属方法返回的是一个对象集合




    作者:乐鱼播客JavaEE培训学院
    首发:http://
    Java.itcast.cn/
    0 分享到:
    和我们在线交谈!
    【网站地图】【sitemap】