单向many2one
单向many2one是最简单的对象关系。但是在Mybatis中设计对象映射,需要摒弃在hibernate中的一些既有思路,更多的需要从SQL和性能角度考虑映射关系。先来看看对象的关系,在这里使用Customer和Orders对象来完成单向的many2one。对象设计如下:
//客户对象
public class Customer {
private Long id;
private String name;
//getter & setter;
}
//订单对象
public class Orders {
private Long id;
private String sn;
private Double price;
//订单包含一个客户对象
private Customer customer;
}
对象很好理解。下面是Customer的映射文件。Customer对象是一个很简单的对象,他的映射文件也很简单:
上面的映射中,主要把关键的保存和获取方法列举出来。接着是Orders对象,在Orders中主要需要处理的是保存和获取方法。需要注意的是:1,保存,因为有一个外键的关联关系,所以,必须按照顺序先保存Customer对象,再保存Orders对象。2,获取Orders对象。在之前的文档中已经说到,获取关联对象有两种方法,一是使用另一条SELECT+延迟加载的方式获取,二是采用内嵌的映射方式。而第一种方式在列表的时候会出现N+1问题,所以,我们采用内嵌的映射方式:<mapper namespace="cd.itcast.mybatis.customer"> <insert id="save" keyProperty="id" parameterType="Customer" useGeneratedKeys="true"> INSERT INTO customer(name) values (#{name}) </insert> <select id="get" resultType="Customer" parameterType="int"> SELECT * FROM customer WHERE id = #{id} </select> </mapper>
需要注意2点,一是保存的时候,使用属性连接的方式得到CUSTOMER_ID的值;二是在获取对象的时候,使用两表连接的方式内联映射Orderds对象中的Customer对象。<mapper namespace="cd.itcast.mybatis.orders"> <resultMap type="Orders" id="ordersmap"> <id property="id" column="id"/> <result property="sn" column="sn"/> <result property="price" column="price"/> <!-- 使用内联的映射完成Customer对象的属性设置 --> <association property="customer" column="customer_id" javaType="Customer"> <id property="id" column="cid"/> <result property="name" column="cname"/> </association> </resultMap> <insert id="save" keyProperty="id" parameterType="Orders" useGeneratedKeys="true"> INSERT INTO orders(sn,price,cust_id) values (#{sn},#{price},#{customer.id,jdbcType=BIGINT}) </insert> <select id="get" parameterType="int" resultMap="ordersmap"> SELECT c.* as cid,c.name as cname,o.* FROM orders o LEFT JOIN customer c on o.customer_id = c.id WHERE o.id = #{id} </select> <select id="list" resultMap="ordersmap"> SELECT c.id as cid,c.name as cname,o.* FROM orders o LEFT JOIN customer c on o.customer_id = c.id </select> </mapper>
可能会问,如果在列表中只需要使用到Orders对象本身,如果采用这种方式会额外的开销结果集的大小。个人的建议是,对于这种情况,也不需要使用额外的SQL+延迟加载去加载Orders对应的Customer,而直接映射一个不需要关系的Orders对象列表,比如:
<select id="listOrders" resultType="Orders">
SELECT * FROM orders
</select>
这样采用另外的一个select完成映射,也算是按需使用。 版权声明:本文为lanyotechcs原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。