2016-11-29 62 views
1

的無需擔心持續性,我已經設計了一個類來保存的(不同尺寸)的容器映射不同產品的數量,該產品可以保持在如何定義Hibernate映射在地圖一個地圖

class Inventory { 
    Long        id; 
    Map <Long, Map<Long,Integer>> productQuantityByContainer; // ProductId->(ContainerId -> quantity) 
} 

與產品和容器類作爲

class Product { 
    Long id; 
    String name; 
} 

class Container { 
    Long  id; 
    Double size; 
} 

後兩者有直接的Hibernate的映射到其對應的數據庫表。我需要使用Hibernate映射文件(的hbm.xml)和我的數據庫有如下信息(不考慮Hibernate的約束):

Product table 
-------------- 
ID|Name 
1 Milk 
2 Orange Juice 

Container table 
--------------- 
ID |Size(oz) 
10 32 
11 64 

Inventory table (first 2 columns form the PK) 
--------------- 
Product-ID(FK) | Container-ID(FK) | Quantity 
    1    10     25 
    1    11     15 
    2    10     33 

我的問題是:我的理解休眠不允許收藏地圖的持久性。所以爲了使Hibernate能夠從我的Inventory類中持久保存信息,是否可以使我的設計和映射如下所示? (我創建兩個類ContainerQuantity和數量具有相同名稱的兩個映射表如下圖所示),請批評/下面看看我HBM映射。

class Inventory { // <--- Redesigned ---> 
    Long  id; 
    Map <Long, ContainerQuantity> cqsByProduct; // ProductId->ContainerQty 
} 

<class name="Inventory"> <!-- hbm mapping --> 
    <id name="id"/> 
    <map name="cqsByProduct"> 
     <key column="Inventory_ID" not-null="true"/> 
     <map-key column="Product_ID" 
     <one-to-many class="ContainerQuantity"/> 
    </map> 
</class> 

Inventory table (in Database) 
--------------- 
    id 
90210 
90211 

class ContainerQuantity { 
    Long     id; 
    Map<Long,Integer>  quantitiesByContainer; 
} 

<class name="ContainerQuantity"> <!-- hbm mapping --> 
    <id name="id"/> 
    <map name="quantitiesByContainer"> 
     <key column="CQ_ID" not-null="true"/> 
     <map-key column="Container_ID" 
     <one-to-many class="Quantity"/> 
    </map> 
</class> 

ContainerQuantity table (for holding the cqsByProduct collection) 
------------------------ 
    id  | Product_ID | Inventory_ID (FK to collection owner) 
    101   1   90210 
    102   1   90210 
    103   2   90210 

class Quantity { 
    Integer    quantity; 
    Container    container; 
    ContainerQuantity  cq;   
} 

<class name="Quantity"> <!-- hbm mapping --> 
    <composite-id> 
     <key-many-to-one name="container" class="Container" column="Container_ID" /> 
     <key-many-to-one name="cq" class="ContainerQuantity" column="CQ_ID" /> 
    </composite-id>  
</class> 

Quantity table (for holding quantitiesByContainer collection) 
-------------------- 
Container_ID(FK) | Quantity | CQ_ID (FK to collection owner) 
    10    25   101 
    11    15   102 
    10    33   103 

回答

0

多磨難之後(並且沒有答案的SO即將出版),我找到了解決我自己的問題。希望這將有助於未來的其他人。我沒有簡化我的設計以擺脫Quantity類,因爲ContainerQuantity中的地圖可以只是一個值集合。然而,值得注意的是,不具有數量級不會從數據庫中有一個「數量」表阻止我們。

// classes defined in package hibtest 
public class Inventory { 
    Long   id; 
    String   name; 
    Map <Product, ContainerQuantity> cqsByProduct; 

    public Inventory() 
    //..getters and setters for each of above 
} 

public class ContainerQuantity { 
    Long     id; 
    Inventory    inventory; 
    Map<Container,Integer>  quantitiesByContainer; 

    public ContainerQuantity() 
    //..getters and setters for each of above 
} 

最難的部分就是它竟然是Hibernate映射右:

<hibernate-mapping> 
    <class name="hibtest.Inventory" table="INVENTORY"> 
    <id name="id" column="INVENTORY_ID"> 
     <generator class="sequence"> 
      <param name="sequence">DON.NEXT_INVENTORY_ID</param> 
     </generator> 
    </id> 
    <property name="name" column="name" type="string"/> 
    <map name="cqsByProduct" inverse="true" cascade="all"> <!-- inverse=true ensures INVENTORY_ID in CONTAINERQUANTITY table is set by hibtest.ContainerQuantity --> 
     <key column="INVENTORY_ID" not-null="true"/> 
     <map-key-many-to-many column="PRODUCT_ID" class="hibtest.Product"/> 
     <one-to-many class="hibtest.ContainerQuantity"/> 
    </map> 
    </class> 

    <class name="hibtest.ContainerQuantity" table="CONTAINERQUANTITY"> 
    <id name="id" column="CQ_ID"> 
     <generator class="sequence"> 
      <param name="sequence">DON.NEXT_CONTAINERQUANTITY_ID</param> 
     </generator> 
    </id> 

    <many-to-one name="inventory" class="hibtest.Inventory" column="INVENTORY_ID" not-null="true" /> <!-- column will be set when row inserted into CONTAINERQUANTITY table --> 

    <map name="quantitiesByContainer" table="QUANTITY" cascade="all" > <!-- inverse is false so CQ_ID in QUANTITY will be set by ContainerQuantity --> 
     <key column="CQ_ID" not-null="true"/> 
     <map-key-many-to-many column="CONTAINER_ID" class="hibtest.Container"/>  
     <element column="quantity" type="int"/> 
    </map> 
    </class> 
</hibernate-mapping> 

我的表看起來那麼(甲骨文SQL):

create table product 
(
    id    NUMBER(22) not null, 
    name    VARCHAR2(32) not null); 

create table container 
(
    id    NUMBER(22) not null, 
    name   VARCHAR2(32) not null); 

create table inventory 
(
INVENTORY_ID    NUMBER(22) not null, 
name      VARCHAR2(32) not null); 

create table containerquantity 
(
cq_id     NUMBER(22) not null, 
product_id    NUMBER(22), 
inventory_id    NUMBER(22)); 

create table quantity 
(
quantity     NUMBER(10) not null, 
container_id    NUMBER(22) not null, 
cq_id     NUMBER(22) not null); 

這裏是驅動程序代碼:

private static void persist(Session session){ 
    Product product1 = new Product(); 
    Product product2 = new Product();  
    product1.setName("Apple"); 
    product2.setName("Milk"); 

    Container c1 = new Container(); 
    Container c2 = new Container(); 
    c1.setName("32 oz"); 
    c2.setName("64 oz"); 

    //-- Make container-qty1 and add 2 quantity entries into it 
    ContainerQuantity cq1 = new ContainerQuantity(); 

    Map<Container,Integer>  quantitiesByContainer1 = new HashMap<Container,Integer>(); 

    quantitiesByContainer1.put(c1, Integer.valueOf(25)); 
    quantitiesByContainer1.put(c2, Integer.valueOf(15)); 
    cq1.setQuantitiesByContainer(quantitiesByContainer1); 

    //-- Make container-qty2 and add 1 quantity entry into it 
    ContainerQuantity cq2 = new ContainerQuantity(); 

    Map<Container,Integer>  quantitiesByContainer2 = new HashMap<Container,Integer>(); 

    quantitiesByContainer2.put(c1, Integer.valueOf(33)); 
    cq2.setQuantitiesByContainer(quantitiesByContainer2); 

    //-- Make Inventory object 
    Inventory inv = new Inventory(); inv.setName("foods"); 
    Map <Product, ContainerQuantity> cqsByProduct = new HashMap<Product, ContainerQuantity>(); 
    cqsByProduct.put(product1, cq1); 
    cqsByProduct.put(product2, cq2); 

    //-- Set back-reference to inventory on ContainerQuantity objects 
    cq1.setInventory(inv); 
    cq2.setInventory(inv); 

    inv.setCqsByProduct(cqsByProduct);  

    session.save(product1); 
    session.save(product2); 
    session.save(c1); 
    session.save(c2); 

    session.save(inv);  
} 
+0

是否有可能與安來實現這一otations? –