首页 > 其他分享 >MyBatis的注解实现复杂映射开发

MyBatis的注解实现复杂映射开发

时间:2022-09-04 22:45:28浏览次数:54  
标签:12 return 映射 public user MyBatis 注解 id select

xml 配置方式实现复杂映射回顾

实现复杂映射我们之前可以在映射文件中通过配置来实现,使用注解开发后,我们可以通过 @Results 注解,@Result 注解,@One 注解和 @Many 注解组合完成复杂关系的配置。

注解 说明
@Results
代替的是标签 ,该注解中可以使用单个的 @Result 注解,也可以使用 @Result 集合。
使用方式:@Results({@Result(), @Result()}) 或者 @Results(@Result())
@Result
代替了 标签和 标签
@Result 中的属性介绍
column:数据库中的列名
property:要装配的属性名
one:需要使用 @One 注解( @Result(one=@One)()
many:需要使用 @Many 注解( @Result(many=@many)()
@One(一对一) 代替了 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
@One 注解属性介绍
select:指定用来多表查询的 sqlmapper
使用格式:@Result(column="", property="", one=(select=""))
@Many(多对一) 代替了 标签,是多表查询的关键,在注解中用来指定子查询返回对象集合。
使用格式:@Result(property="", column="", many=@many(select=""))

一对一查询

一对一查询的模型

用户表和订单表的关系为,一个用户有多个订单,一共订单只属于一个用户

一对一查询需求:查询一个订单,与此同时查询该订单对应的用户

@startuml

!include https://unpkg.com/plantuml-style-c4@latest/core.puml
' uncomment the following line and comment the first to use locally
'!include core.puml

left to right direction

class orders {
   ordertime: varchar(255)
   total: double
   uid: int(11)
   id: int(11)
}
class user {
   username: varchar(50)
   password: varchar(50)
   birthday: varchar(50)
   id: int(11)
}

orders  -[#595959,plain]-^  user   : "uid:id"
@enduml

一对一查询的语句

对应的 sql 语句

select * from orders;
select * from user where id=查询出订单的uid;

查询结果如下:

id ordertime total uid id username password birthday
1 2019-12-12 3000 1 1 lucy 123 2019-12-12
2 2019-12-12 4000 1 1 lucy 123 2019-12-12
3 2019-12-12 5000 2 1 lucy 123 2019-12-12
1 2019-12-12 3000 1 2 tom 123 2019-12-12

创建 User 和 Order 实体

/**
 * 订单
 *
 * @name: Order
 * @author: terwer
 * @date: 2022-03-17 17:42
 **/
public class Order {
    private Integer id;
    private String orderTime;
    private Double total;

    // 代表当前订单属于哪一个用户
    private User user;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(String orderTime) {
        this.orderTime = orderTime;
    }

    public Double getTotal() {
        return total;
    }

    public void setTotal(Double total) {
        this.total = total;
    }

    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 +
                ", user=" + user +
                '}';
    }
}

/**
 * 用户
 *
 * @name: User
 * @author: terwer
 * @date: 2022-05-25 13:25
 **/
public class User {
    private Integer id;
    private String username;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                '}';
    }
}

创建 IOrderMapper 接口

/**
 * 订单映射
 *
 * @name: IUserMapper
 * @author: terwer
 * @date: 2022-03-17 17:54
 **/
public interface IOrderMapper {
    public List<Order> findOrderAndUser();
}

使用注解配置接口

/**
 * 订单映射
 *
 * @name: IUserMapper
 * @author: terwer
 * @date: 2022-03-17 17:54
 **/
public interface IOrderMapper {
    /**
     * 查询订单同时查询订单所属用户
     *
     * @return
     */
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "orderTime", column = "ordertime"),
            @Result(property = "total", column = "total"),
            @Result(property = "user", column = "uid", javaType = User.class, one = @One(select = "com.terwergreen.mapper.IUserMapper.findUserById"))
    })
    @Select("select * from orders")
    public List<Order> findOrderAndUser();
}
/*
 * 用户映射
 *
 * @name: IUserMapper
 * @author: terwer
 * @date: 2022-05-25 13:27
 **/
public interface IUserMapper {
    /**
     * 根据ID查询用户
     * @param id
     * @return
     */
    @Select("select * from user where id=#{id}")
    User findUserById(Integer id);
}

测试结果

/**
 * 订单测试
 *
 * @name: IOrderMapperTest
 * @author: terwer
 * @date: 2022-08-31 22:52
 **/
public class IOrderMapperTest {
    private IOrderMapper orderMapper;
    private SqlSession sqlSession;

    @Before
    public void before() throws Exception {
        System.out.println("before...");
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        sqlSession = sqlSessionFactory.openSession();
        // 这样也是可以的,这样的话后面就不用每次都设置了
        // sqlSession = sqlSessionFactory.openSession(true);
        orderMapper = sqlSession.getMapper(IOrderMapper.class);
    }

    @Test
    public void testFindOrder() throws Exception {
        List<Order> orderAndUser = orderMapper.findOrderAndUser();

        orderAndUser.forEach(order -> {
            System.out.println(order);
        });
    }
}

效果

Opening JDBC Connection
Created connection 2024453272.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@78aab498]
==>  Preparing: select * from orders
==> Parameters: 
<==    Columns: id, ordertime, total, uid
<==        Row: 1, 2019-12-12, 3000.0, 1
====>  Preparing: select * from user where id=?
====> Parameters: 1(Integer)
<====    Columns: id, username, password, birthday
<====        Row: 1, lucy, 123, 2019-12-12
<====      Total: 1
<==        Row: 2, 2019-12-12, 4000.0, 1
<==        Row: 3, 2019-12-12, 5000.0, 2
====>  Preparing: select * from user where id=?
====> Parameters: 2(Integer)
<====    Columns: id, username, password, birthday
<====        Row: 2, tom, 123, 2019-12-12
<====      Total: 1
<==      Total: 3
Order{id=1, orderTime='2019-12-12', total=3000.0, user=User{id=1, username='lucy'}}
Order{id=2, orderTime='2019-12-12', total=4000.0, user=User{id=1, username='lucy'}}
Order{id=3, orderTime='2019-12-12', total=5000.0, user=User{id=2, username='tom'}}

Process finished with exit code 0

调用过程分析

image-20220901002006366

一对多查询

一对多查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户。

一对多查询需求:查询一个用户,与此同时查出该用户具有的订单。

@startuml

!include https://unpkg.com/plantuml-style-c4@latest/core.puml
' uncomment the following line and comment the first to use locally
'!include core.puml

left to right direction

class orders {
   ordertime: varchar(255)
   total: double
   uid: int(11)
   id: int(11)
}
class user {
   username: varchar(50)
   password: varchar(50)
   birthday: varchar(50)
   id: int(11)
}

orders  -[#595959,plain]-^  user   : "uid:id"
@enduml

一对多查询语句

对应查询语句:

对应的 sql 语句

select * from user;
select * from orders where uid=查询出用户的id;

查询结果如下:

id ordertime total uid id username password birthday
1 2019-12-12 3000 1 1 lucy 123 2019-12-12
2 2019-12-12 4000 1 1 lucy 123 2019-12-12
3 2019-12-12 5000 2 1 lucy 123 2019-12-12
1 2019-12-12 3000 1 2 tom 123 2019-12-12

修改 User 实体

/**
 * 订单
 *
 * @name: Order
 * @author: terwer
 * @date: 2022-03-17 17:42
 **/
public class Order {
    private Integer id;
    private String orderTime;
    private Double total;

    // 代表当前订单属于哪一个用户
    private User user;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(String orderTime) {
        this.orderTime = orderTime;
    }

    public Double getTotal() {
        return total;
    }

    public void setTotal(Double total) {
        this.total = total;
    }

    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 +
                ", user=" + user +
                '}';
    }
}
/**
 * 用户
 *
 * @name: User
 * @author: terwer
 * @date: 2022-05-25 13:25
 **/
public class User {
    private Integer id;
    private String username;

    // 代表当前用户具备那些订单
    private List<Order> orderList;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public List<Order> getOrderList() {
        return orderList;
    }

    public void setOrderList(List<Order> orderList) {
        this.orderList = orderList;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", orderList=" + orderList +
                '}';
    }
}

创建IUserMapper接口

/**
 * 用户映射
 *
 * @name: IUserMapper
 * @author: terwer
 * @date: 2022-05-25 13:27
 **/
public interface IUserMapper {
    /**
     * 查询用户和订单
     *
     * @return
     */
    List<User> findUserAndOrder();
}

使用注解配置Mapper

/**
 * 用户映射
 *
 * @name: IUserMapper
 * @author: terwer
 * @date: 2022-05-25 13:27
 **/
public interface IUserMapper {
    /**
     * 查询用户和订单
     *
     * @return
     */
    @Results({
            @Result(property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "orderList", column = "id", many = @Many(select = "com.terwergreen.mapper.IOrderMapper.findOrderByUid"), javaType = List.class)
    })
    @Select("select * from user")
    List<User> findUserAndOrder();
}
/**
 * 订单映射
 *
 * @name: IUserMapper
 * @author: terwer
 * @date: 2022-03-17 17:54
 **/
public interface IOrderMapper {
    @Select("select * from orders where uid=#{uid}")
    public List<Order> findOrderByUid(Integer uid);
}

测试结果

public class IUserMapperTest {

    private IUserMapper userMapper;
    private SqlSession sqlSession;

    @Before
    public void before() throws Exception {
        System.out.println("before...");
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        sqlSession = sqlSessionFactory.openSession();
        // 这样也是可以的,这样的话后面就不用每次都设置了
        // sqlSession = sqlSessionFactory.openSession(true);
        userMapper = sqlSession.getMapper(IUserMapper.class);
    }

    @Test
    public void testGetUserOrders() {
        List<User> userAndOrder = userMapper.findUserAndOrder();
        userAndOrder.forEach(user -> {
            System.out.println(user);
        });
    }
}

结果如下:

Opening JDBC Connection
Created connection 98394724.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5dd6264]
==>  Preparing: select * from user
==> Parameters: 
<==    Columns: id, username, password, birthday
<==        Row: 1, lucy, 123, 2019-12-12
====>  Preparing: select * from orders where uid=?
====> Parameters: 1(Integer)
<====    Columns: id, ordertime, total, uid
<====        Row: 1, 2019-12-12, 3000.0, 1
<====        Row: 2, 2019-12-12, 4000.0, 1
<====      Total: 2
<==        Row: 2, tom, 123, 2019-12-12
====>  Preparing: select * from orders where uid=?
====> Parameters: 2(Integer)
<====    Columns: id, ordertime, total, uid
<====        Row: 3, 2019-12-12, 5000.0, 2
<====      Total: 1
<==        Row: 8, 测试2, null, null
====>  Preparing: select * from orders where uid=?
====> Parameters: 8(Integer)
<====      Total: 0
<==        Row: 9, 测试3, null, null
====>  Preparing: select * from orders where uid=?
====> Parameters: 9(Integer)
<====      Total: 0
<==      Total: 4
User{id=1, username='lucy', orderList=[Order{id=1, orderTime='2019-12-12', total=3000.0, user=null}, Order{id=2, orderTime='2019-12-12', total=4000.0, user=null}]}
User{id=2, username='tom', orderList=[Order{id=3, orderTime='2019-12-12', total=5000.0, user=null}]}
User{id=8, username='测试2', orderList=[]}
User{id=9, username='测试3', orderList=[]}

Process finished with exit code 0

多对多查询

文章更新历史

2022-08-30 feat:初稿

标签:12,return,映射,public,user,MyBatis,注解,id,select
From: https://www.cnblogs.com/tangyouwei/p/mybatis-s-annotation-achieves-complex-mapping-develop

相关文章

  • MyBatis 五 ---查看详情&&条件查询
    查看详情1、编写接口方法:Mapper接口参数:id返回结果:Brand   2、编写SQL语句:SQL映射文件;参数占位......
  • @FeignClient注解
    @FeignClient注解SpringCloudOpenFeign是SpringCloud团队将原生的Feign结合到SpringCloud中的产物。从上面原生Feign的使用示列来看,用的注解都是Feign中自带的,但......
  • Mybatis学习笔记(三)——Mybatis执行sql的两种方式
    这部分内容前边简单提过了,之前写第一个Mybatis示例时用的就是第一种方式。本节主要介绍MyBatis执行SQL语句的两种方式和它们的区别。MyBatis有两种执行SQL语句的方......
  • 注解Annotation
    注解是一种引用数据类型,重点掌握Deprecated(表示已过时),Override(表示重写)。元注解是用来标注注解类型的注解如Target(用来标注注解可以出现在哪些位置)、Retention(用来标注最......
  • 2.注解开发springmvc
    通用配置:<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-i......
  • 注解
    注解Annotation     元注解meta-annotation(相当于自定义注解)元注解  target(value=)表示这个注解可以用在什么地方value可以传几个值ElementType.可以看源码......
  • mybatis之MetaObject
    MetaObject元数据对象,底层肯定是反射,通过反射来进行设置值。这个可以来操作对象中的属性,哪怕是组合方式,无论有多少层,这个都可以来进行操作。举例如下所示:publicclass......
  • Mybatis学习笔记(二)——Mybatis核心对象
    1.Mybatis核心对象MyBatis有三个基本要素:核心接口和类MyBatis核心配置文件(mybatis-config.xml)SQL映射文件(mapper.xml)1.1核心接口和类每个MyBatis应用程序都以......
  • Mybatis学习笔记(一)——简介
     1.Mybatis是什么MyBatis是一个开源、轻量级的数据持久化框架,是JDBC和Hibernate的替代方案。MyBatis内部封装了JDBC,简化了加载驱动、创建连接、创建statement......
  • MyBatis 三
    设置别名    安装MyBatisx插件可以很方便的管理 ......