hibernate一对多,多对多映射

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是通过实体类操作数据库的,这里就贴实体类的代码

订单类

public class Order {

    private int order_id;
    private String order_no;

    //变量属性一定要用接口接收
    //描述一个订单对应多个订单项
    public Set<OrderItem> getOrderitems() {
        return orderitems;
    }

    public void setOrderitems(Set<OrderItem> orderitems) {
        this.orderitems = orderitems;
    }

    private Integer initorderitems = 0;//0懒加载 1强制加载

    public Integer getInitorderitems() {

        return initorderitems;
    }

    public void setInitorderitems(Integer initorderitems) {
        this.initorderitems = initorderitems;
    }

    private Set<OrderItem> orderitems = new HashSet<>();

    public int getOrder_id() {
        return order_id;
    }

    public void setOrder_id(int order_id) {
        this.order_id = order_id;
    }

    public String getOrder_no() {
        return order_no;
    }

    public void setOrder_no(String order_no) {
        this.order_no = order_no;
    }
}

订单项类

public class OrderItem {
    private int order_item_id;
    private int product_id;
    private int quantity;
    private int oid;
//多个订单项对应一个订单
    private Order order;

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public int getOrder_item_id() {
        return order_item_id;
    }

    public void setOrder_item_id(int order_item_id) {
        this.order_item_id = order_item_id;
    }

    public int getProduct_id() {
        return product_id;
    }

    public void setProduct_id(int product_id) {
        this.product_id = product_id;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public int getOid() {
        return oid;
    }

    public void setOid(int oid) {
        this.oid = oid;
    }
}

然后这里普通的映射就不贴代码啦,请去看以前的博客

因为订单和订单项是一对多的关系

<!--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>
		<!--对应list集合-->
		<!--<list name="">-->
			<!--<key></key>-->
		<!---->
		<!--</list>-->
		<!--<bag name="">-->
			<!--<key></key>-->

		<!--</bag>-->

订单项是多对一 

<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的主控方会自动维护
  

其实用的最多的还是一对多的关系,多对多可以看成两个一对多

猜你喜欢

转载自blog.csdn.net/yjt520557/article/details/84491749