Explain Mybatis in simple terms (eight) advanced mapping

    The previous chapters use operations on a single table, but in actual development, many tables need to be associated. At this time, we need to use our advanced mapping, including one-to-one, one-to-many and many-to-many many.

Let's first analyze a simple business scenario.

There are four tables:

User table: user saves user-related information.

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL COMMENT 'username',
  `birthday` date DEFAULT NULL COMMENT 'birthday',
  `sex` varchar(255) DEFAULT NULL COMMENT 'sex',
  `addr` varchar(255) DEFAULT NULL COMMENT 'Addr',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Add test data:


Commodity table: items store information related to commodities.

CREATE TABLE `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  `detail` varchar(255) DEFAULT NULL,
  `pic` varchar(255) DEFAULT NULL,
  `createtime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Add test data:


Order table: Orders saves order information, associated with the user table user, and an order corresponds to a user user.

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Order number',
  `user_id` int(11) NOT NULL,
  `number` int(32) NOT NULL,
  `createtime` datetime NOT NULL,
  `note` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Add test data:


Order details: orderdetail An order contains multiple items.

CREATE TABLE `orderdetail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orders_id` int(11) NOT NULL,
  `items_id` int(11) NOT NULL,
  `items_num` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `orders_id` (`orders_id`),
  KEY `items_id` (`items_id`),
  CONSTRAINT `orderdetail_ibfk_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`),
  CONSTRAINT `orderdetail_ibfk_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Add test data:


The first requirement is to query the order and associate the user's information.

Create the orders class,

public class Orders {
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;

    public Integer getId() {
        return id;
    }

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

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

   
}

sql statement

 
 
select orders.*,user.username,user.sex,user.addr from orders,user WHERE orders.user_id=user.id

1: Use resultType for mapping.

 
 
<!-- Query order related query user-->
    <select id="findOrdersUser" resultType="OrdersCustom">
        select orders.*,user.username,user.sex,user.addr from orders,user WHERE orders.user_id=user.id
    </select>
Since there is no user-related information in the orders class, it is necessary to use an extended class to inherit orders and add user attributes.
 
 
/**
 * @author:kevin
 * @description: the extension class of the order
 * Through this type of mapping order and user query results, let this type of inheritance include pojo classes with more fields
 * @create 2018-03-31 9:40
 */
public class OrdersCustom extends Orders{
    //add property
    private String username;
    private String sex;
    private String addr;

    public String getUsername() {
        return username;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }
    
}
Create a new interface OrdersMapperCustom and xml OrdersMapperCustom.xml under the current package
Change the namespace in xml to the path of the interface
com.beyond.mybatis.mapper.OrdersMapperCustom
<!-- Query order related query user-->
    <select id="findOrdersUser" resultType="OrdersCustom">
        select orders.*,user.username,user.sex,user.addr from orders,user WHERE orders.user_id=user.id
    </select>

Add the corresponding method to the interface.

//Query order association query user information
    List<OrdersCustom> findOrdersUser() throws Exception;
test:
 
 
@Test
    public void testfindOrdersUser() throws Exception{
        SqlSession sqlSession = factory.openSession();
        //Get the proxy object of UserMapper through reflection
        OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
        List<OrdersCustom> list = ordersMapperCustom.findOrdersUser();
        System.out.println(list);
    }
Debug through breakpoints and view the values ​​in the list:
Three records were found:

2: Use resultMap for mapping

Add a property User in the orders class.

<!-- Query order related query users, use resultMap -->
    <select id="findOrdersUserResultMap" resultMap="ordersUserResultMap">
        select orders.*,user.username,user.sex,user.addr from orders,user WHERE orders.user_id=user.id
    </select>
<!-- Order query associated user's resultMap -->
    <resultMap id="ordersUserResultMap" type="Orders">
        <!-- Configure the mapped order information-->
        <!-- id: Specify the unique identifier in the query column. If multiple columns form a unique identifier, configure multiple ids -->
        <id column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
        <!-- Configure the associated user information of the mapping -->
        <!-- association: used to map the association query information of a single object
            property: which property in Orders to map the user information of the associated query to
         -->
        <association property="user" javaType="com.beyond.mybatis.po.User">
            <!-- id: The unique ID of the associated query user
                column: Specify the column that uniquely identifies the user information
                javaType: which property maps to user
             -->
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="addr" property="addr"/>
        </association>
    </resultMap>
//Query order association query user information, resultMap
    List<Orders> findOrdersUserResultMap() throws Exception;
test:
@Test
    public void testfindOrdersUser() throws Exception{
        SqlSession sqlSession = factory.openSession();
        //Get the proxy object of UserMapper through reflection
        OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
        List<Orders> list = ordersMapperCustom.findOrdersUserResultMap();
        System.out.println(list);
    }
Breakpoint debugging on it:
 
 
 
 

Summary of resultType and resultMap when implementing one-to-one query:

resultType: It is very simple to use. If the queried column name is not included in the pojo, you need to add the attribute corresponding to the column name to complete the mapping.

If there are no special requirements for query results, it is recommended to use resultType.

resultMap: resultMap needs to be defined separately, which is a bit troublesome to implement. If there are special requirements for query results, use resultMap to complete the

Associated queries are mapped into pojo properties.

resultMap can implement lazy loading, and resultType cannot implement lazy loading.

The second requirement is to query orders and order details, one-to-many query

Main table: orders

Association table: orderdetail

sql statement:

<!-- Query order related query user and order details, use resultMap -->
    <select id="findOrdersAndOrderDetailResultMap" resultMap="ordersAndOrderDetailResultMap">
        select
            orders.*,
            user.username,
            user.sex,
            user.addr,
            orderdetail.id orderdetail_id,
            orderdetail.items_id,
            orderdetail.items_num,
            orderdetail.orders_id
        from
            orders,
            user,
            orderdetail
        where
            orders.user_id=user.id
        and
            orders.id=orderdetail.orders_id
    </select>


Then you need to add an orderDetails property to the orders class and generate get and set methods.
 
 

Define resultMap:

Since the information of the order and user is defined above, it can be directly inherited here;

<!-- Query the resultMap of order and order details -->
    <resultMap id="ordersAndOrderDetailResultMap" type="orders" extends="ordersUserResultMap">
        <!-- Order information, obtained through inheritance-->
        <!-- User information, obtained through inheritance-->
        <!-- order details
            Collection: Map the multiple records from the associated query to the collection
            property: which property in orders to map
            ofType: the type of pojo in the collection attribute
         -->
        <collection property="orderDetails" ofType="com.beyond.mybatis.po.OrderDetail">
            <!-- primary key-->
            <id column="orderdetail_id" property="id"/>
            <!--Normal column-->
            <result column="items_id" property="itemsId"/>
            <result column="items_num" property="itemsNum"/>
            <result column="orders_id" property="orderId"/>
        </collection>
    </resultMap>
Add interface method:
 
 
//Query order association Query order details
    List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;
test:
 
 
@Test
    public void testfindOrdersAndOrderDetailResultMap() throws Exception{
        SqlSession sqlSession = factory.openSession();
        //Get the proxy object of UserMapper through reflection
        OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
        List<Orders> list = ordersMapperCustom.findOrdersAndOrderDetailResultMap();
        System.out.println(list);
    }
Use breakpoint debugging to observe the list collection.
There are two orders in total. The first order belongs to the user with id and contains three order details (that is, three items).
 
 
 
 

The third requirement is to query users and the products purchased by users, many-to-many

Main table: user

Idea: Add the attribute of the order list to the user, List<Orders> orders

Add the properties of the order details list in orders, List<OrderDetail> orderDetails;

Add product attributes in orderDetail, Items items,

sql statement:

<!-- Query user and product information purchased by user, use resultMap -->
    <select id = "findUsersAndItemsResultMap" resultMap = "usersAndItemsResultMap">
        select
            orders.*,
            user.username,
            user.sex,
            user.addr,
            orderdetail.id orderdetail_id,
            orderdetail.items_id,
            orderdetail.items_num,
            orderdetail.orders_id,
            items.name items_name,
            items.detail items_detail,
            items.price items_price
        from
            orders,
            user,
            orderdetail,
            items
        where
            orders.user_id=user.id
        and
            orders.id=orderdetail.orders_id
        and
            orderdetail.items_id=items.id
    </select>
Add to the User class: private List<Orders> orders; generate get and set methods.
The Orders class has been added above,

The Orders class has been added above, and adding the Items property in the OrderDetail also generates get and set methods.

    Write resultMap:

    

<!-- Query the user and the product information purchased by the user-->
    <resultMap id="usersAndItemsResultMap" type="user">
        <!-- User Information-->
        <id column="user_id" property="userId"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="addr" property="addr"/>
        <!-- One user corresponds to multiple order information-->
        <collection property="orders" ofType="com.beyond.mybatis.po.Orders">
            <id column="id" property="id"/>
            <result column="user_id" property="userId"/>
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
            <!-- One order corresponds to multiple order details-->
            <collection property="orderDetails" ofType="com.beyond.mybatis.po.OrderDetail">
                <!-- primary key-->
                <id column="orderdetail_id" property="id"/>
                <!--Normal column-->
                <result column="items_id" property="itemsId"/>
                <result column="items_num" property="itemsNum"/>
                <result column="orders_id" property="orderId"/>
                <!-- An order detail corresponds to a product information-->
                <association property="items" javaType="com.beyond.mybatis.po.Items">
                    <id column="items_id" property="id"/>
                    <result column="items_name" property="name"/>
                    <result column="items_detail" property="detail"/>
                    <result column="items_price" property="price"/>
                </association>
            </collection>
        </collection>
    </resultMap>

Write the interface method:

//Query the user and the product information purchased by the user
    List<User> findUsersAndItemsResultMap() throws Exception;

test:

@Test
    public void testfindUsersAndItemsResultMap() throws Exception{
        SqlSession sqlSession = factory.openSession();
        //Get the proxy object of UserMapper through reflection
        OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
        List<User> list = ordersMapperCustom.findUsersAndItemsResultMap();
        System.out.println(list);
    }

Breakpoint debugging to view the information of the list:

A total of two users have orders,

A user purchased three items: ASUS, Lenovo and Shenzhou


Another user bought two items: ASUS and Apple



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325547274&siteId=291194637