1.什么是关联?
关联指的是类之间的引用关系。如果类A与类B关联,那么被引用的类B将被定义为类A的属性。例如:
public class A{
private B b = new B;
public A(){}
}
1.2 关联的分类:
关联可以分为一对一、一对多/多对一、多对多关联 关联是有方向的
#关键点都在数据库中的外键上面,请好好理解下面这二句SQL和一对多及多对一的关系
#select * from Orders where cid=? //这条SQL返回客户对应的0-n个订单
#select * from Customers where customerId=? //这条SQL返回订单对应的1个客户
#通过这二条SQL不难看出,外键在这里有二个用途:查找客户的订单,查找订单对应的客户
2.那么如何建立一个一对多的关联呢
因为hibernate是通过实体类操作数据库的,这里就贴实体类的代码
订单类:(记得定义get and set)
public class Order {
private int order_id;
private String order_no;
//变量属性一定要用接口接收
//描述一个订单对应多个订单项
private Set<OrderItem> orderitems = new HashSet<>();
private Integer initorderitems = 0;//0懒加载 1强制加载
}
订单项类
public class OrderItem {
private int order_item_id;
private int product_id;
private int quantity;
private int oid;
//多个订单项对应一个订单
private Order order;
}
然后这里普通的映射就不贴代码啦,请去看以前的博客
因为订单和订单项是一对多的关系
<!--cascade:级联属性配置 建议不配置del可能会造成迭代删除-->
<!--inverse:关联关系交给别人维护么?-->
<set name="orderitems" inverse="true" cascade="save-update">
<!--对应外键-->
<key column="oid"></key>
<one-to-many class="com.zking.three.OrderItem"></one-to-many>
</set>
订单项是多对一
<many-to-one insert="false" update="false" name="order" class="com.zking.three.Order" column="oid"></many-to-one>
在这里可能会报一个错Repeated column in mapping for entity: com.zking.three.OrderItem column: oid
解决方法 加上insert="false" update="false" 或者加在oid属性中或者在实体类中删除哦id属性都可一解决
3.1 lazy:默认值为true,true延迟加载,false立即加载(一般设置为true,不使用立即加载,因为影响查询性能)查询的时候如果报错有很大的可能是因为懒加载的原因
Lazy=true介绍 查单个时存在问题
Lazy=false介绍 查所有时存在问题
所以使用Hibernate.initialize()来强制加载某个属性来解决
public Order get(Order order){
Session session = SessionFactoryUtils.openSession();
Transaction transaction = session.beginTransaction();
Order o=session.get(order.getClass(),order.getOrder_id());
if(o!=null&&order.getInitorderitems().equals(new Integer(1))){
Hibernate.initialize(o.getOrderitems());
}
transaction.commit();
session.close();
return o;
}
3.2 outter-join:默认值为false,true使用左外联接查询关联的(但一般不用,因为当我们把该属性设置为true时,所有的查询语句 都会默认左外联,那样性能不高)
3.3 inverse:默认值为false,true表示将对方设置为主控方(一对多双向关联中一般将多方设置为主控方,这样可以减少SQL语句的数量,减少多余的操作)
3.4 cascade:用来控制如何操作关联的持久化对象的
3.4.1 none:保存,更新或删除当前对象时,忽略其它关联的对象
3.4.2 save-update:保存、更新时级联保存所有的临时对象,并且级联更新关联的游离对象
3.4.3 delete:通过session的delete方法删除当前对象,级联删除关联的对象
4.多对多
举个例子一本书可以对应多个类别,一个类别也可以对应多本书这就是多对多
<!--name:指的是当前映射实体的属性-->
<!--table:对应的是中间表-->
<!--关联关系是否交给对方维护 只要有一方维护即可-->
<!--inverse="true" cascade="save-update"只要一方维护就好-->
<set name="categorys" table="t_hibernate_book_category" >
<!--指的是中间表字段(与当前映射实体对应的表的主键相关联的id)-->
<key column="bid"></key>
<!-- class:多方的全类名
cloumn:与多方主键相关联的字段
-->
<many-to-many class="com.zking.four.Category" column="cid"></many-to-many>
</set>
</class>
<!--name:指的是当前映射实体的属性-->
<!--table:对应的是中间表-->
<!--关联关系是否交给对方维护-->
<set name="books" table="t_hibernate_book_category" inverse="true" cascade="save-update">
<!--指的是中间表字段(与当前映射实体对应的表的主键相关联的id)-->
<key column="cid"></key>
<!-- class:多方的全类名
cloumn:与多方主键相关联的字段
-->
<many-to-many class="com.zking.four.Book" column="bid"></many-to-many>
</set>
4.3. 多对多关系注意事项
4.3.1 一定要定义一个主控方
4.3.2 多对多删除
4.3.2.1 主控方直接删除
4.3.2.2 被控方先通过主控方解除多对多关系,再删除被控方
4.3.2.3 禁用级联删除
4.3.3 关联关系编辑,不需要直接操作桥接表,hibernate的主控方会自动维护
其实用的最多的还是一对多的关系,多对多可以看成两个一对多