때때로 부모 / 자식 개체 또는 다 대다 관계에서 SaveOrUpdate
또는 을 호출해야합니다 Merge
. 일반적으로을 호출해야 할 때 호출시 SaveOrUpdate
발생하는 예외 Merge
는 먼저 저장되지 않는 임시 객체와 관련이 있습니다.
둘의 차이점을 설명 해주세요.
답변:
이것은 섹션 10.7 에서 가져온 것 입니다. Hibernate 참조 문서의 자동 상태 감지 :
saveOrUpdate ()는 다음을 수행합니다.
- 객체가이 세션에서 이미 영구적 인 경우 아무 작업도 수행하지 않습니다.
- 세션과 관련된 다른 개체에 동일한 식별자가 있으면 예외를 throw합니다.
- 객체에 식별자 속성이 없으면 save ()
- 객체의 식별자에 새로 인스턴스화 된 객체에 할당 된 값이 있으면 save ()
- 객체의 버전이 지정되고 (<version> 또는 <timestamp>에 의해) 버전 속성 값이 새로 인스턴스화 된 객체에 할당 된 동일한 값인 경우 save ()
- 그렇지 않으면 객체를 update ()
merge ()는 매우 다릅니다.
- 현재 세션과 연결된 동일한 식별자를 가진 영구 인스턴스가있는 경우 지정된 개체의 상태를 영구 인스턴스에 복사합니다.
- 현재 세션과 연결된 영구 인스턴스가없는 경우 데이터베이스에서로드하거나 새 영구 인스턴스를 만듭니다.
- 영구 인스턴스가 반환됩니다.
- 주어진 인스턴스는 세션과 연결되지 않고 분리 된 상태로 유지됩니다.
세션에서 분리 된 한 지점에 있던 객체를 업데이트하려는 경우 Merge ()를 사용해야합니다. 특히 현재 세션과 연관된 객체의 영구 인스턴스가있을 수있는 경우에는 더욱 그렇습니다. 그렇지 않으면 SaveOrUpdate ()를 사용하면 예외가 발생합니다.
SaveOrUpdateCopy
동일하지 않습니다 SaveOrUpdate
. 질문자가 Merge
전자와 후자 를 비교 하고 싶은지 확실하지 않습니다 . 가져 SaveOrUpdateCopy
오기 전에 NHibernate에서 병합을 수행 한 지금은 사용되지 않는 방법입니다 Merge
.
SaveOrUpdateCopy()
이제 NHibernate 3.1에서 더 이상 사용되지 않습니다. Merge()
대신 사용해야합니다.
SaveOrUpdateCopy
표시되는 Obsolete
,하지 SaveOrUpdate
. 이 질문과 후속 답변에서이 두 가지 다른 방법 사이에 많은 혼란이있는 것 같습니다.
나는 발견 이 예외의 유형을 설명하는 아주 좋은 일을 한 링크를 :
나를 위해 일한 것은 다음과 같습니다.
cascade="merge"
SaveOrUpdate
부모 개체에 할당하기 전에 먼저 자식 / 종속 개체.SaveOrUpdate
부모 개체.그러나이 솔루션에는 한계가 있습니다. 즉, 최대 절전 모드를 사용하는 대신 자녀 / 종속 개체를 저장해야합니다.
누구든지 더 나은 솔루션이 있다면보고 싶습니다.
@Entity
@Table(name="emp")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="emp_id")
private int id;
@Column(name="emp_name")
private String name;
@Column(name="salary")
private int Salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return Salary;
}
public void setSalary(int salary) {
this.Salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public enum HibernateUtil {
INSTANCE;
HibernateUtil(){
buildSessionFactory();
}
private SessionFactory sessionFactory=null;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private void buildSessionFactory() {
Configuration configuration = new Configuration();
configuration.addAnnotatedClass (TestRefresh_Merge.Employee.class);
configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");
configuration.setProperty("hibernate.connection.username", "root");
configuration.setProperty("hibernate.connection.password", "root");
configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
configuration.setProperty("hibernate.hbm2ddl.auto", "update");
configuration.setProperty("hibernate.show_sql", "true");
configuration.setProperty(" hibernate.connection.pool_size", "10");
/* configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");
configuration.setProperty(" hibernate.cache.use_query_cache", "true");
configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");
*/
// configuration
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
setSessionFactory(sessionFactory);
}
public static SessionFactory getSessionFactoryInstance(){
return INSTANCE.getSessionFactory();
}
}
public class Main {
public static void main(String[] args) {
HibernateUtil util=HibernateUtil.INSTANCE;
SessionFactory factory=util.getSessionFactory();
//save(factory);
retrieve(factory);
}
private static void retrieve(SessionFactory factory) {
Session sessionOne=factory.openSession();
Employee employee=(Employee)sessionOne.get(Employee.class, 5);
sessionOne.close(); // detached Entity
employee.setName("Deepak1");
Session sessionTwo=factory.openSession();
Employee employee1=(Employee)sessionTwo.get(Employee.class, 5);
sessionTwo.beginTransaction();
sessionTwo.saveOrUpdate(employee); // it will throw exception
//sessionTwo.merge(employee); // it will work
sessionTwo.getTransaction().commit();
sessionTwo.close();
}
private static void save(SessionFactory factory) {
Session sessionOne=factory.openSession();
Employee emp=new Employee();
emp.setName("Abhi");
emp.setSalary(10000);
sessionOne.beginTransaction();
try{
sessionOne.save(emp);
sessionOne.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
sessionOne.close();
}
}
}