
第一节 概念
第二节 对一
第三节 对多
第四节 分步查询
第五节 延迟加载]
第六节 多对多关联关系需要中间表
文章目录一对一
夫妻关系,人和身份证号
一对多
用户和用户的订单,锁和钥匙
多对多
老师和学生,部门和员工
public class Customer {
private Integer customerId;
private String customerName;
private List orderList;// 体现的是对多的关系
public class Order {
private Integer orderId;
private String orderName;
private Customer customer;// 体现的是对一的关系
双向关联关系:双方都能够引用到对方
Customer中能够引用Order
Order中能够引用Customer
在双向关联关系中使用toString()等方法时注意避免无限死循环。
②创建数据库表插入测试数据单向关联关系:双方中只有一方能够引用到对方
Customer中没有引用Order
Order中引用了Customer
CREATE TABLE `t_customer` (
`customer_id` INT NOT NULL AUTO_INCREMENT,
`customer_name` CHAr(100),
PRIMARY KEY (`customer_id`)
);
CREATE TABLE `t_order` (
`order_id` INT NOT NULL AUTO_INCREMENT,
`order_name` CHAr(100),
`customer_id` INT,
PRIMARY KEY (`order_id`)
);
INSERT INTO `t_customer` (`customer_name`) VALUES ('c01');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o1', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o3', '1');
实际开发时,一般在开发过程中,不给数据库表设置外键约束。
原因是避免调试不方便。
一般是功能开发完成,再加外键约束检查是否有bug。
[
第二节 对一 1、创建OrderMapper接口public interface OrderMapper {
Order selectOrderWithCustomer(Integer orderId);
}
2、创建OrderMapper.xml配置文件
3、在Mybatis全局配置文件中注册Mapper配置文件
4、junit测试程序
@Test
public void testRelationshipToOne() {
SqlSession session = factory.openSession();
OrderMapper orderMapper = session.getMapper(OrderMapper.class);
// 查询Order对象,检查是否同时查询了关联的Customer对象
Order order = orderMapper.selectOrderWithCustomer(2);
System.out.println("order = " + order);
session.close();
}
5、关键词
在“对一”关联关系中,我们的配置比较多,但是关键词就只有:association和javaType
第三节 对多 1、创建Mapper接口public interface CustomerMapper {
Customer selectCustomerWithOrderList(Integer customerId);
}
2、创建CustomerMapper.xml配置文件
注意:不要忘记在Mybatis全局配置文件中注册
3、配置关联关系和SQL语句4、junit测试
@Test
public void testRelationshipToMulti() {
SqlSession session = factory.openSession();
CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
// 查询Customer对象同时将关联的Order集合查询出来
Customer customer = customerMapper.selectCustomerWithOrderList(1);
System.out.println("customer.getCustomerId() = " + customer.getCustomerId());
System.out.println("customer.getCustomerName() = " + customer.getCustomerName());
List orderList = customer.getOrderList();
for (Order order : orderList) {
System.out.println("order = " + order);
}
session.close();
}
5、关键词
在“对多”关联关系中,同样有很多配置,但是提炼出来最关键的就是:“collection”和“ofType”
第四节 分步查询 1、概念和需求为了实现延迟加载,对Customer和Order的查询必须分开,分成两步来做,才能够实现。为此,我们需要单独查询Order,也就是需要在Mapper配置文件中,单独编写查询Order集合数据的SQL语句。
2、具体操作 ①编写查询Customer的SQL语句②编写查询Order的SQL语句 ③引用SQL语句
如果Mapper接口中的抽象方法没有改变,那么juni测试也不变。执行结果如下:
DEBUG 11-30 11:10:05,796 ==> Preparing: select customer_id,customer_name from t_customer where customer_id=? (BaseJdbcLogger.java:145)
DEBUG 11-30 11:10:05,866 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 11-30 11:10:05,889 ====> Preparing: select order_id,order_name from t_order where customer_id=? (BaseJdbcLogger.java:145)
DEBUG 11-30 11:10:05,890 ====> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 11-30 11:10:05,895 <==== Total: 3 (BaseJdbcLogger.java:145)
DEBUG 11-30 11:10:05,896 <== Total: 1 (BaseJdbcLogger.java:145)
customer = c01
order = Order{orderId=1, orderName='o1'}
order = Order{orderId=2, orderName='o2'}
order = Order{orderId=3, orderName='o3'}
④各个要素之间的对应关系
第五节 延迟加载
1、概念
查询到Customer的时候,不一定会使用Order的List集合数据。如果Order的集合数据始终没有使用,那么这部分数据占用的内存就浪费了。对此,我们希望不一定会被用到的数据,能够在需要使用的时候再去查询。
例如:对Customer进行1000次查询中,其中只有15次会用到Order的集合数据,那么就在需要使用时才去查询能够大幅度节约内存空间。
延迟加载的概念:对于实体类关联的属性到需要使用时才查询。也叫懒加载。
2、配置在Mybatis全局配置文件中配置settings
3、修改junit测试官方文档中对aggressiveLazyLoading属性的解释:
When enabled, an object with lazy loaded properties will be loaded entirely upon a call to any of the lazy properties.Otherwise, each property is loaded on demand.
@Test
public void testSelectCustomerWithOrderList() throws InterruptedException {
SqlSession session = sessionFactory.openSession();
CustomerMapper mapper = session.getMapper(CustomerMapper.class);
Customer customer = mapper.selectCustomerWithOrderList(1);
// 这里必须只打印“customerId或customerName”这样已经加载的属性才能看到延迟加载的效果
// 这里如果打印Customer对象整体则看不到效果
System.out.println("customer = " + customer.getCustomerName());
// 先指定具体的时间单位,然后再让线程睡一会儿
TimeUnit.SECONDS.sleep(5);
List orderList = customer.getOrderList();
for (Order order : orderList) {
System.out.println("order = " + order);
}
session.commit();
session.close();
}
效果:刚开始先查询Customer本身,需要用到OrderList的时候才发送SQL语句去查询
DEBUG 11-30 11:25:31,127 ==> Preparing: select customer_id,customer_name from t_customer where customer_id=? (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:31,193 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:31,314 <== Total: 1 (BaseJdbcLogger.java:145)
customer = c01
DEBUG 11-30 11:25:36,316 ==> Preparing: select order_id,order_name from t_order where customer_id=? (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:36,316 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:145)
DEBUG 11-30 11:25:36,321 <== Total: 3 (BaseJdbcLogger.java:145)
order = Order{orderId=1, orderName='o1'}
order = Order{orderId=2, orderName='o2'}
order = Order{orderId=3, orderName='o3'}
4、关键词总结
我们是在“对多”关系中举例说明延迟加载的,在“对一”中配置方式基本一样。
| 关联关系 | 配置项关键词 | 所在配置文件 |
|---|---|---|
| 对一 | association标签/javaType属性 | Mapper配置文件中的resultMap |
| 对多 | collection标签/ofType属性 | Mapper配置文件中的resultMap |
| 对一分步 | association标签/select属性 | Mapper配置文件中的resultMap |
| 对多分步 | collection标签/select属性 | Mapper配置文件中的resultMap |
| 延迟加载 | lazyLoadingEnabled设置为true aggressiveLazyLoading设置为false | Mybatis全局配置文件中的settings |
在某一个表中,使用一个字段保存多个“外键”值,这将导致无法使用SQL语句进行关联查询。
2、使用中间表这样就可以使用SQL进行关联查询了。只是有可能需要三张表进行关联。
3、中间表设置主键 ①方案一:另外设置一个专门的主键字段 ②方案二:使用联合主键使用联合主键时,只要多个字段的组合不重复即可,单个字段内部是可以重复的。
|