Понимание NonUniqueObjectException в спящем режиме
Пытаясь понять больше о Hibernate, я написал некоторый код, который создает некоторые сущности и сохраняет их в БД, а затем пытается удалить одну из сущностей.
Файл отображения для объекта Customer имеет генератор идентификаторов, установленный на native.Ib Postgresql используется как db.
...
<class name="Customer" table="CUSTOMER">
<id column="CUSTOMER_ID" name="customer_id" type="java.lang.Long">
<generator class="native"/>
</id>
...
Я сталкивался с hibernate.NonUniqueObjectException.
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.me.hibernatestore.Customer#129]
Полная трассировка стека здесь
Я запустил отладчик eclipse и обнаружил, что задействованный объект имеет одинаковый адрес во всех задействованных методах.
Соответствующая часть кода
public class Main {
CustomerDao custdao;
Customer mark;
public void storeDemo(){
custdao = DaoFactory.getCustomerDao();
createCustomers();
updateEntities();
deleteCustomer(mark);
}
private void createCustomers() {
mark = new Customer();
mark.setName("mark");
mark.setEmailAddress("mark@home");
mark.setAddress("121,3rd avenue");
mark.setCity("San Diego");
mark.setState("CA");
mark.setCountry("U.S.A");
}
private void updateEntities() {
Transaction tx = null;
Session session = HibernateUtil.getCurrentSession();
try{
tx = session.beginTransaction();
custdao.saveOrUpdateCustomer(mark);
tx.commit();
}catch(RuntimeException e){
tx.rollback();
throw e;
}
}
private void deleteCustomer(Customer cust){
Transaction tx = null;
Session session = HibernateUtil.getCurrentSession();
try{
tx = session.beginTransaction();
String custName = cust.getName();
custdao.deleteCustomer(cust);
tx.commit();
}catch(RuntimeException e){
tx.rollback();
throw e;
}
}
public static void main(String[] args) {
new Main().storeDemo();
}
}
С помощью отладчика я нашел адрес объекта 'mark'
Main.createCustomers(): mark-> Customer@2bc3f5
CustomerDaoImpl.saveOrUpdateCustomer(Customer customer):customer-> Customer@2bc3f5
BaseDaoImpl.saveOrUpdate(T obj):obj-> Customer@2bc3f5
Main.deleteCustomer(Customer customer):customer-> Customer@2bc3f5
CustomerDaoImpl.deleteCustomer(Customer customer):customer-> Customer@2bc3f5
BaseDaoImpl.delete(T obj):obj-> Customer@2bc3f5
Экспериментируя далее, я изменил код и через dao.findById() получил другой объект с тем же идентификатором и использовал его в deleteCustomer(). На этот раз код работал без каких-либо исключений.
public class Main {
CustomerDao custdao;
Customer mark;
public void storeDemo(){
custdao = DaoFactory.getCustomerDao();
createCustomers();
updateEntities();
Long mark_id = mark.getCustomer_id();
Customer mark2 = getCustomer(mark_id);
deleteCustomer(mark2);
}
private Customer getCustomer(Long id){
Transaction tx = null;
Customer cust = null;
Session session = HibernateUtil.getCurrentSession();
try{
tx = session.beginTransaction();
return custdao.findCustomerById(id);
}catch(RuntimeException e){
throw e;
}
}
...
}
Может кто-нибудь объяснить это поведение? Мое понимание того, что часть сообщения об ошибке "другой объект с одинаковым значением идентификатора" нечеткий. Объект, показанный в отладчике в первом случае, имеет один и тот же адрес памяти везде в коде. это может быть другой объект?
Искренне
Джим
1 ответ
Это исключение обычно возникает при работе с отсоединенными объектами. Чтобы избежать этого, вы должны получить объект и удалить его в том же сеансе или повторно присоединить его к сеансу, а затем удалить его. Надеюсь это поможет!