【问题标题】:hibernate many to many mappings for join table with extra columns , surrogate key, additional primary key休眠多对多映射,用于具有额外列、代理键、额外主键的连接表
【发布时间】:2011-08-08 19:01:38
【问题描述】:

我很难为以下场景(来自遗留数据库)解析实体映射(使用注释)

场景 1:

Table A
  A_ID (PK)

Table B    
  B_ID (PK)

TABLE A_B    
  AB_ID (PK)    
  A_ID (FK)    
  B_ID (FK)    
  Created_DATE

场景 2:

Table A    
  A_ID (PK)

Table B    
  B_ID (PK)

TABLE A_B    
  AB_ID (PK)    
  A_ID (PK)(FK)    
  Test_Date (PK)    
  B_ID (FK)    
  Created_DATE

场景 3:

Table A
  A_ID (PK)             
  A2_ID (PK)

Table B    
  B_ID (PK)

TABLE A_B    
  A_ID (PK)(FK)    
  A2_ID (PK)(FK)    
  B_ID (PK)(FK)   
  Created_DATE

能否使用注释和解释在休眠中显示这些实体?

【问题讨论】:

  • 嗯,还没有一个答案吗?

标签: hibernate nhibernate nhibernate-mapping hibernate-annotations


【解决方案1】:
Table Products
  Product_Id(PK)
  Product_Name
  Price

Table Orders
  Order_Id(PK)
  Order_Date
  Total

Table Order_Products
  Order_Id(FK)(PK)
  Product_Id(FK)(PK)
  Quantity

 @Entity
  public class OrderProducts{

     @Embeddable
     public static class IdClass {

        @ManyToOne
        @JoinColumn(name = "Product_Id")
        private Products p;

        @ManyToOne
        @JoinColumn(name = "Order_Id")
        private Orders o;
   }

   @Id
   private IdClass id = new IdClass();
   private Integer quantity;
  }

  @Entity
  public class Products{
     @ID
     private Integer id;

     @OneToMany(mappedBy="id.p") // this is the tricky part 'id.p'
     Set<OrderProducts> ops = new Set<OrderProducts>();

   }

类似于订单。

【讨论】:

    【解决方案2】:

    为了更清楚,我会给你一个类似的场景:

    场景 1:

    Table Products
       Product_Id(PK)
       Product_Name
       Price
    Table Orders
       Order_Id(PK)
       Order_Date
       Total
    Table Order_Products
       Order_Product_Id(PK) (Surrogate key)
       Order_Id(FK)
       Product_Id(FK)
       Quantity
    

    在此域中,OrdersProducts 表之间存在多对多关系,如下所示:

    • 一个订单有很多产品。
    • 一个产品可能属于多个订单。

    当我们映射这种多对多关系时,Order_Products 文件映射将不包含该关系的任何实现,它将由两个多对多映射(两个包或两个类中的两个集合)表示两边的关系如下:

    对于 Products.hbm:

    <class name="Products" table="Products">
       <id name="Product_Id" column="Product_Id">
           <generator class="native"/>
       </id>
       <bag name="Orders" generic="true" table="Orders_Products">
          <key column="Product_Id"/>
          <many-to-many column="Add_Orders_Id" class="Orders"/>
       </bag>
    ...and other properties
    </class>
    

    订单.hbm:

    <class name="Orders" table="Orders">
       <id name="Order_Id" column="Order_Id">
           <generator class="native"/>
       </id>
       <bag name="Products" generic="true" table="Order_Products">
           <key column="Orders_Id"/> 
           <many-to-many column="Product_Id" class="Products"/>
       </bag>
    ...
    

    这意味着Products 表中的Product_IdOrders 表中的Order_Id 具有多对多关系。

    注意,包中的表tag是多对多映射表,是关系的中间点,包内的Order_Id是关联的Order_Products中的FK到Products 表。

    两个包的名字就是Products类中代表多对多关系的两个类中的两个集合的名字:

        public virtual IList<Orders> Orders
        {
            get;
            set;
        }
    

    Orders 类中,您有一个产品列表:

        public virtual IList<Products> Products
        {
            get;
            set;
        }
    

    在 Order_Products.hbm 中,您根本不需要为这种关系做任何事情,但是如果表 Order_Products 仅包含外键并且没有其他属性,则您不必映射表,例如,如果它没有 Quantity 属性:

      <class name="Order_Products" table="Order_Products">
        <id name="Order_Product_Id" column="Order_Product_Id">
          <generator class="native" />
        </id>
        <property name="Quantity" type="Decimal" column="Quantity" />
      </class> 
    

    在其他两种情况下,我认为您将遵循相同的映射,只是您将使用复合键(a &lt;composite-id&gt;)来映射附加的复合主键,但映射将是相同的。

    对于另外两个场景,老实说,我自己没有尝试过复合ID的映射,但我认为关系会以相同的方式,复合键不会影响关系,但是Hibernate团队强烈不推荐使用复合键。

    为了简单起见,我忽略了 xml 映射中的很多代码。

    【讨论】:

    • 谢谢@MGA,我认为代理键对于休眠逆向工程来说很容易,我的意思是场景1。由于连接表具有唯一键,因此没有复合键涉及,因此休眠可以处理此连接表(带有附加列)作为简单实体。但是,如果 FK 将作为 PK 参加,那么事情就会变得更丑陋。
    猜你喜欢
    • 2013-10-21
    • 2012-05-12
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    相关资源
    最近更新 更多