我正在研究Hibernate的父/子關係。休眠父/子關係。爲什麼對象保存兩次?
我有3個實體Employee
Customers
和Orders
。
它們的關係是
- >ñOrders
- >ñOrders
我希望能夠保存/更新/刪除Customer
對象和Employees
和Orders
但我想使用一些接口,以便調用代碼不處理任何Hibernate或JPA的東西。
E.g.我試着像下面這樣:
class Utils{
public static void saveObject(Object o){
logger.debug(o.toString());
Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(o);
tx.commit();
session.close();
}
}
,並在調用代碼我做的:
Employee employee = new Employee();
//set data on employee
Customer customer = new Customer();
//set data on customer
Order order = new Order();
//set data on order
employee.addOrder(order);//this adds order to its list, order gets a reference of employee as parent
customer.addOrder(order);//this adds order to its list, order gets a reference of customer as parent
Utils.saveObject(customer);
Utils.saveObject(employee);
現在我發現這個代碼,2條記錄員工創建的1
代替如果我只做:
Utils.saveObject(customer);
只有1個(正確)記錄被創建。
爲什麼會發生這種情況?
發生這種情況是因爲Customer
和Employee
都保存了相同的Order
對象嗎?而cascade="all"
會造成這種副作用?
現在,如果我不使用DBUtils
方法,直接做:
Session session = DBUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(employee);
session.save(customer);
tx.commit();
session.close();
再次,它工作正常。即僅創建1個員工記錄。
我在這裏做錯了什麼?
UPDATE:
休眠映射:
<hibernate-mapping>
<class name="database.entities.Associate" table="EMPLOYEE">
<id name="assosiateId" type="java.lang.Long">
<column name="EMPLOYEEID" />
<generator class="identity" />
</id>
<property name="firstName" type="java.lang.String" not-null="true">
<column name="FIRSTNAME" />
</property>
<property name="lastName" type="java.lang.String" not-null="true">
<column name="LASTNAME" />
</property>
<property name="userName" type="java.lang.String" not-null="true">
<column name="USERNAME" />
</property>
<property name="password" type="java.lang.String" not-null="true">
<column name="PASSWORD" />
</property>
<set name="orders" table="ORDERS" inverse="true" cascade="all" lazy="true">
<key>
<column name="EMPLOYEEID" />
</key>
<one-to-many class="database.entities.Order" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="database.entities.Customer" table="CUSTOMER">
<id name="customerId" type="java.lang.Long">
<column name="CUSTOMERID" />
<generator class="identity" />
</id>
<property name="customerName" type="java.lang.String">
<column name="CUSTOMERNAME" />
</property>
<set name="orders" table="ORDERS" inverse="true" cascade="all" lazy="true">
<key>
<column name="CUSTOMERID" />
</key>
<one-to-many class="database.entities.Order" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="database.entities.Order" table="ORDERS">
<id name="orderId" type="java.lang.Long">
<column name="ORDERID" />
<generator class="identity" />
</id>
<property name="orderDate" type="java.util.Date">
<column name="ORDERDATE" />
</property>
<property name="quantity" type="java.lang.Integer">
<column name="QUANTITY" />
</property>
<property name="quantityMargin" type="java.lang.Long">
<column name="QUANTITYMARGIN" />
</property>
<property name="port" type="java.lang.String">
<column name="PORT" />
</property>
<property name="orderState" type="java.lang.String">
<column name="ORDERSTATE" />
</property>
<many-to-one name="customer" class="database.entities.Customer" cascade="all" fetch="join">
<column name="CUSTOMERID" />
</many-to-one>
<many-to-one name="associate" column="EMPLOYEEID" class="database.entities.Employee" cascade="all" fetch="join">
</many-to-one>
</class>
</hibernate-mapping>
UDATE 2:
class Employee{
//Various members
Set<Order> orders = new HashSet<Order>();
public void addOrder(Order order){
order.setEmployee(this);
orders.add(order);
}
}
另請參見:
class Customer{
//Various members
Set<Order> orders = new HashSet<Order>();
public void addOrder(Order order){
order.setCustomer(this);
orders.add(order);
}
}
你能告訴你的Hibernate映射? – artgon
我已經用映射更新了文章。 – Cratylus
您的交易處理是完全錯誤的。交易不僅僅是存儲實體所需的東西。它應該是一個原子工作單位。必須保持一致的數據庫所有更新必須在唯一事務內完成。 –