一 建表,提供初始数据。
表说明:t_customer为客户信息表;t_orders为订单表。一个客户可以有多个订单,一个订单只属于一个客户。多方使用外键(t_orders表的customer_id)来约束。这里并没有建立强制的外键约束,做更新,删除操作时会很麻烦。
CREATE TABLE `t_customer` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, `cell_phone` varchar(30) NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO `t_customer` VALUES ('1', 'bing', '652346543'); INSERT INTO `t_customer` VALUES ('2', 'jade', '76345'); CREATE TABLE `t_orders` ( `id` int(10) NOT NULL AUTO_INCREMENT, `number` varchar(40) NOT NULL, `address` varchar(40) NOT NULL, `customer_id` int(10) NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO `t_orders` VALUES ('1', 'GASDF235', '北京朝阳', '1'); INSERT INTO `t_orders` VALUES ('2', 'JHGFVSD34', '河南郑州', '1'); INSERT INTO `t_orders` VALUES ('3', 'KJHGFDC234', '北京海淀', '2');
表模型如下
二 实体类
Customer
package com.alex.app.entity; import java.util.List; /** * 客户信息 * @author leileiyuan * */ public class Customer { private Integer id; private String name; private String cellPhone; //一对多 private List<Orders> orders; public List<Orders> getOrders() { return orders; } public void setOrders(List<Orders> orders) { this.orders = orders; } // 略 getter setter方法 @Override public String toString() { return "Customer [id=" + id + ", name=" + name + ", cellPhone=" + cellPhone + "]"; } }
Orders
package com.alex.app.entity; /** * 客户订单信息 * @author leileiyuan * */ public class Orders { private Integer id; private String number; private String address; // 多对一 private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } // 略 getter setter方法 @Override public String toString() { return "Orders [id=" + id + ", number=" + number + ", address=" + address + ", customer=" + customer + "]"; } }
三 多对一映射
1)问题简单分析
从orders 到 customer 多对一的关联关联。
就是说 我们要查询orders的信息,然后经该orders可以导航到它对应的customer
考虑这个sql
select o.*, c.* from t_orders o join t_customer c on o.customer_id = c.id where o.id = 2
查询是没有问题的
映射文件配置时可以。
<select id="selectById" parameterType="int" resultMap="???????"> select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_orders o join t_customer c on o.customer_id = c.id where o.id = #{id} </select>
因为我们查询的结果集中包含的是orders和customer的所有列,所以返回的结果集应该使用resultMap而不是resultType(也可以也写一个VO,来封装结果中的列,那么就可以使用resultType指向那个VO)。
2)映射结果集
我们来写个resultMap 来封装这个复杂结果集
Orders.xml的映射文件如下。t_orders和t_customer的id列,要使用别名来区分
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.alex.app.dao.OrdersDao"> <resultMap type="Orders" id="OrdersResultMap"> <id property="id" column="oid"/> <result property="number" column="number"/> <result property="address" column="address"/> </resultMap> <select id="selectById" parameterType="int" resultMap="OrdersResultMap"> select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_orders o join t_customer c on o.customer_id = c.id where o.id = #{id} </select> </mapper>
定义了一个resultMap,id为OrdersResultMap,查询的结果集指向这个resultMap。
来测试下
@Test public void test() { SqlSession session = null; try { session = MyBatisUtil.openSession(); OrdersDao ordersDao = session.getMapper(OrdersDao.class); Orders orders = ordersDao.selectById(1); System.out.println(orders); } catch (Exception e) { e.printStackTrace(); session.rollback(); }finally{ MyBatisUtil.coloseSession(session); } }
结果如下
Orders [id=1, number=GASDF235, address=北京朝阳, customer=null]
customer为null。
3)表达关联关系
我们还需要把orders到customer多对一,这个一方,也表示在resultMap里。使用association 标签。
t_orders和t_customer的id列,要使用别名来区分
<resultMap type="Orders" id="OrdersResultMap"> <id property="id" column="oid"/> <result property="number" column="number"/> <result property="address" column="address"/> <association property="customer" javaType="Customer"> <id property="id" column="cid"/> <result property="name" column="name"/> <result property="cellPhone" column="cell_phone"/> </association> </resultMap>
association解释
属性:property,当然是Orders实体中定义的属性名customer;
javaType,是customer所要映射成那个Java对象,这可以使用别名
子标签:
id,表示主键,property是实体类的属性名,column是对应表的字段列名
result,表示普通属性
4)再运行上面的测试代码,得到结果
Orders [id=1, number=GASDF235, address=北京朝阳, customer=Customer [id=1, name=bing, cellPhone=null, orders=null]]看到我们已经关联上了,也返回了正确的结果。
5)Orders.xml完整内容。t_orders和t_customer的id列,要使用别名来区分
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.alex.app.dao.OrdersDao"> <resultMap type="Orders" id="OrdersResultMap"> <id property="id" column="oid"/> <result property="number" column="number"/> <result property="address" column="address"/> <association property="customer" javaType="Customer"> <id property="id" column="cid"/> <result property="name" column="name"/> <result property="cellPhone" column="cell_phone"/> </association> </resultMap> <select id="selectById" parameterType="int" resultMap="OrdersResultMap"> select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_orders o join t_customer c on o.customer_id = c.id where o.id = #{id} </select> </mapper>
四 一对多关联映射
从customer到orders一对多的关联关系。一个客户对多个订单信息
1)问题分析
考虑这个sql
select c.*, o.* from t_customer c join t_orders o on c.id = o.customer_id where c.id = 1
查询结果bing这个客户拥有两个订单
2)映射结果集
映射文件的sql
<select id="selectById" parameterType="int" resultMap="CustomerResultMap"> select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_customer c, t_orders o where c.id = o.customer_id and c.id = #{id} </select>
3)一对多关联
上面我们需要提供一个resultMap="CustomerResultMap"。t_orders和t_customer的id列,要使用别名来区分
<resultMap type="Customer" id="CustomerResultMap"> <id property="id" column="cid" /> <result property="name" column="name" /> <collection property="orders" javaType="ArrayList" ofType="Orders"> <id property="id" column="oid" /> <result property="number" column="number" /> </collection> </resultMap>
一对多关联,多的一方使用collection表示
collection 属性 解释:
property,是实体类中的属性orders;
javaType,这里的JavaType代表的是实体类中的属性orders的类型是ArrayList
//一对多 private List<Orders> orders;
ofType,是集合中的放置的内容的类型,这里集合放的东西是Orders对象
4)测试下
@Test public void testSelectCustomer() { SqlSession session = null; try { session = MyBatisUtil.openSession(); CustomerDao customerDao = session.getMapper(CustomerDao.class); Customer customer = customerDao.selectById(1); System.out.println(customer); List<Orders> orders = customer.getOrders(); System.out.println(orders); } catch (Exception e) { e.printStackTrace(); }finally{ MyBatisUtil.coloseSession(session); } }
结果
DEBUG 2015-05-10 08:59:28,640 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Preparing: select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_customer c, t_orders o where c.id = o.customer_id and c.id = ? DEBUG 2015-05-10 08:59:28,687 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters: 1(Integer) DEBUG 2015-05-10 08:59:28,718 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <== Total: 2 Customer [id=1, name=bing, cellPhone=null, orders=[Orders [id=1, number=GASDF235, address=null, customer=null], Orders [id=2, number=JHGFVSD34, address=null, customer=null]]] [Orders [id=1, number=GASDF235, address=null, customer=null], Orders [id=2, number=JHGFVSD34, address=null, customer=null]]
5)Customer.xml完整内容。t_orders和t_customer的id列,要使用别名来区
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.alex.app.dao.CustomerDao"> <resultMap type="Customer" id="CustomerResultMap"> <id property="id" column="cid" /> <result property="name" column="name" /> <collection property="orders" javaType="ArrayList" ofType="Orders"> <id property="id" column="oid" /> <result property="number" column="number" /> </collection> </resultMap> <select id="selectById" parameterType="int" resultMap="CustomerResultMap"> select c.id cid, c.name name, c.cell_phone cellPhone, o.id oid, o.number number, o.address address from t_customer c, t_orders o where c.id = o.customer_id and c.id = #{id} </select> </mapper>
相关推荐
本篇文章将深入探讨"一对多"、"多对一"以及"一对多双向关联"的概念,并结合实际例子进行详细讲解。 首先,我们来看"一对多"(One-to-Many)关系。在现实生活中,一个学生可以对应多个课程,这就是典型的"一对多...
本篇文章将深入探讨 Hibernate 中的一对多双向关联映射。 在数据库设计中,一对多关联是指一个实体可以与多个其他实体相关联,比如一个学生可以有多个课程,一个部门可以有多名员工。在Hibernate中,这种关系可以...
MyBatis处理多对多时,通常会创建一个关联表,然后通过resultMap来映射这两个实体的联合。在映射文件中,需要定义两个双向的association元素,分别表示从一个实体到另一个实体的导航。 4. **SQL查询**: 在MyBatis...
常见的关联关系包括多对一、一对多以及多对多。MyBatis提供了多种方法来处理这些关联查询,包括嵌套结果、嵌套查询等。 #### 三、关联查询类型详解 ##### 1. 多对一 - **概念**: 在多对一的关系中,多个实体对应...
3. **插件集成**:IntelliJ IDEA支持各种插件,MyBatis插件就是其中之一,它可以提供对MyBatis的集成支持,如代码自动完成、XML和Java类的双向导航、SQL预览等。 4. **MyBatis Plus**:MyBatis Plus是对MyBatis的...
2. 双向一对多:两个实体类互相引用,需注意避免循环引用。 3. 多对一:多个实体类引用同一个实体类,一般在被引用实体类中定义关联属性。 ## 九、Mybatis的插件 Mybatis提供拦截器机制,可以通过实现Interceptor...
2. 一对多(One-to-Many):一个实体可以对应多个其他实体实例。比如,一个班级有多个学生。可以通过@OneToMany注解定义,通常使用集合如List来存储子实体。 3. 多对多(Many-to-Many):多个实体可以对应多个其他...
4. BidirectionalOneToMany:双向一对多关联,一个实体可以有多个相关联的实体,而每个子实体只能关联到一个父实体。这种关系在数据库中通常由外键表示,在Hibernate中,可以通过@ManyToOne和@OneToMany注解来实现...
5. 通常,健身房管理系统会包含会员管理、课程管理、预约管理、教练管理等多个模块,因此数据库设计会包括会员表、课程表、预约表、教练表等,这些表之间的关系可能是多对一、一对多或一对一。 6. 数据库设计需要...
14. MyBatis的一对一和一对多实现: 包括注解方式和XML配置方式,涉及单向和双向关联,需要正确设置外键和关联属性。 15. 延迟加载: MyBatis默认不支持延迟加载,但可以通过启用二级缓存和配置`...
例如,可能有员工表、部门表、任务表等,它们之间可能存在多对一、一对多等关联关系。 9. **前端路由与组件化**:Vue.js的单文件组件(SFC)和Vue Router可以让前端页面实现动态路由和组件化开发,提高代码复用性,...
8. **分类与标签**:文章可以被归类到不同的类别,也可能关联多个标签,便于用户按需浏览。 9. **权限控制**:根据用户角色的不同,显示不同的操作按钮或页面,例如管理员可以管理所有文章,而普通用户只能查看和...
这种双向查询常见于一对多或多对一的关系中,例如在商品与商品类型的业务场景下,一个商品对应一个或多个商品类型,而一个商品类型可能对应多个商品。 在MyBatis中实现这种关联查询,通常会涉及到Mapper接口和对应...
WebSocket是一种在客户端与服务器之间建立长连接的协议,它提供了双向通信的能力,使得服务器可以主动向客户端推送数据,而不仅仅是响应客户端的请求。在Java Web开发中,SpringBoot结合MyBatis和MySQL数据库构建...
1. **数据绑定**:Vue.js的双向数据绑定使得界面与数据模型紧密关联,任何一方的改变都会立即反映到另一方。 2. **组件化**:通过组件化的开发方式,可以将复杂的UI拆分为多个可复用的小组件,提高代码的可维护性和...
标题 "基于ssm+vue图片素材网站.zip" 暗示了一个项目,它结合了SSM(Spring、SpringMVC、MyBatis)后端框架和Vue.js前端框架,用于构建一个图片素材网站。这个项目可能包含从用户界面设计到数据库交互的完整实现。 ...