不用担心持久性,我设计了一个类来保存由(不同大小的)容器映射的不同产品的数量,产品可以保存在
中df.astype({c: int for c in slc})
将Product和Container类作为
class Inventory {
Long id;
Map <Long, Map<Long,Integer>> productQuantityByContainer; // ProductId->(ContainerId -> quantity)
}
后两者对其相应的数据库表具有直接的Hibernate映射。我需要使用Hibernate映射文件(hbm.xml),我的数据库有以下信息(不考虑Hibernate的约束):
class Product {
Long id;
String name;
}
class Container {
Long id;
Double size;
}
我的问题是:我理解Hibernate不允许持久存储集合。因此,要使Hibernate持久保存来自Inventory类的信息,我的设计和映射是否足以满足以下要求? (我创建了两个类ContainerQuantity和Quantity,带有两个同名的映射表,如下所示)请批评/检查下面的hbm映射。
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
答案 0 :(得分:0)
经过多次苦难(并且没有答案即将发布),我找到了解决自己问题的方法。希望这将有助于其他人。我确实简化了我的设计以摆脱Quantity类,因为ContainerQuantity中的地图可以只是一个值集合。但是,值得注意的是,没有Quantity类并不能阻止我们在数据库中使用“数量”表。
// 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>
我的表看起来如此(Oracle 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);
}