IT

Hibernate에서 persist () 대 save ()의 장점은 무엇입니까?

lottoking 2020. 6. 5. 08:12
반응형

Hibernate에서 persist () 대 save ()의 장점은 무엇입니까?


누구든지 Hibernate에서 persist()vs 의 장점이 무엇인지 말해 줄 수 있습니까 save()?


에서 이 포럼 게시물

persist()잘 정의되어 있습니다. 임시 인스턴스를 지속적으로 만듭니다. 그러나 식별자 값이 영구 인스턴스에 즉시 할당되는 것을 보장하지는 않으며 할당시 플러시 시간이 발생할 수 있습니다. 사양에 나와 있지 않은 문제가 있습니다 persist().

persist()또한 트랜잭션 경계 외부에서 호출 된 경우 INSERT 문을 실행하지 않도록 보장합니다. 이것은 확장 된 세션 / 지속성 컨텍스트를 가진 장기 대화에서 유용합니다.

같은 방법 persist()이 필요합니다.

save()동일한 것을 보장하지 않고, 식별자를 반환하며, 식별자를 얻기 위해 INSERT를 실행해야하는 경우 (예 : "시퀀스"가 아닌 "ID"생성기)이 INSERT는 내부 또는 외부에 관계없이 즉시 발생합니다. 거래. 확장 된 세션 / 지속성 컨텍스트를 가진 장기 대화에서는 좋지 않습니다.


로컬 컴퓨터에서 여러 번 실행하는 것을 포함하여 save () vs persist ()에 대한 훌륭한 연구를 수행했습니다. 이전의 모든 설명이 혼란스럽고 정확하지 않습니다. 철저한 연구 끝에 아래 save () 및 persist ()를 비교했습니다.

Save()

  1. 저장 후 생성 된 ID를 반환합니다. 그것의 Serializable반환 형식.
  2. 값을 DB에 즉시 저장하고 세션이 끝날 때까지 엔티티를 추적합니다 (트랜잭션 외부에서 엔티티 값을 변경하려고 시도했지만 세션 커밋시 아무런 영향을 미치지 않습니다)
  3. 트랜잭션 외부의 DB에 변경 사항을 저장하십시오.
  4. 생성 된 ID를 유지중인 엔티티에 할당
  5. 분리 된 객체에 대한 Session.save ()는 테이블에 새로운 행을 만듭니다.

Persist()

  1. 저장 후 생성 된 ID를 반환하지 않습니다. void 리턴 타입입니다.
  2. 값을 DB에 즉시 저장하고 세션이 끝날 때까지 엔티티를 추적합니다 (트랜잭션 외부에서 엔티티 값을 변경하려고 시도했지만 세션이 커밋 될 때 아무런 영향을 미치지 않습니다)
  3. 트랜잭션 외부의 DB에 대한 변경 사항을 저장하지 않습니다.
  4. generated id지속중인 엔터티 에을 할당합니다
  5. session.persist()분리 된 객체는 PersistentObjectException허용되지 않으므로 throw 됩니다.

이 모든 것은에 시도 / 테스트되었습니다 Hibernate v4.0.1.


나는 사이의 차이를 기록하는 테스트 일부 모의 한 save()persist().

이 두 가지 방법 모두 일시적인 엔티티를 처리 할 때 동일하게 작동하지만 분리 된 엔티티를 처리 할 때는 다릅니다.

아래 예의 경우 EmployeeVehicle을 vehicleId생성 된 값인 PK를 가진 엔티티 vehicleName특성 중 하나로 사용하십시오.

예 1 : 과도 객체 다루기

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

결과:

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

이미 유지 된 객체를 가져 와서 저장할 때 결과는 동일합니다.

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

같은 것을 반복해서 사용 persist(entity)하면 새로운 Id와 같은 결과가 나옵니다 (37, 혼다).

예 2 : 분리 된 객체 다루기

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

결과 : 이전 세션에서 얻은 id : 36의 차량이 "Toyota"라는 이름으로 업데이트 될 것으로 예상 할 수 있습니다. 그러나 새로운 엔티티가 생성되고 이름이 "Toyota"인 새 엔티티가 DB에 저장됩니다.

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

지속성을 사용하여 분리 된 엔티티 유지

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

결과:

Exception being thrown : detached entity passed to persist

따라서 Transient 객체를 다룰 때 save를 신중하게 사용해야하므로 Save () 대신 Persist ()를 사용하는 것이 좋습니다.

중요 참고 : 위의 예에서 차량 엔티티의 pk는 생성 된 값이므로 save ()를 사용하여 분리 된 엔티티를 유지하면 최대 절전 모드가 유지 될 새 ID를 생성합니다. 그러나이 pk가 생성 된 값이 아닌 경우 키를 위반 한 예외가 발생합니다.


이 질문 에는 최대 절전 모드의 다양한 지속성 방법에 대한 좋은 답변이 있습니다. 질문에 직접 대답하기 위해 save ()를 사용하면 트랜잭션 상태에 관계없이 insert 문이 즉시 실행됩니다. 삽입 된 키를 반환하므로 다음과 같이 할 수 있습니다.

long newKey = session.save(myObj);

따라서 영구 인스턴스에 즉시 할당 된 식별자가 필요한 경우 save ()를 사용하십시오.

persist ()를 사용하면 insert 문이 트랜잭션에서 실행되지만 반드시 즉시 실행되는 것은 아닙니다. 대부분의 경우에 바람직합니다.

트랜잭션에서 삽입이 순서대로 발생하지 않고 삽입 된 키를 리턴 할 필요가없는 경우 persist ()를 사용하십시오.


save()- As the method name suggests, hibernate save() can be used to save entity to database. We can invoke this method outside a transaction. If we use this without transaction and we have cascading between entities, then only the primary entity gets saved unless we flush the session.

persist()-Hibernate persist is similar to save (with transaction) and it adds the entity object to the persistent context, so any further changes are tracked. If the object properties are changed before the transaction is committed or session is flushed, it will also be saved into database. Also, we can use persist() method only within the boundary of a transaction, so it’s safe and takes care of any cascaded objects. Finally, persist doesn't return anything so we need to use the persisted object to get the generated identifier value.


Here is the differences which help you get advantage of persist and save method:

  • First difference between save and persist is there return type. The return type of persist method is void while return type of save
    method is Serializable object.
  • The persist() method doesn’t guarantee that the identifier value will be assigned to the persistent state immediately, the assignment might happen at flush time.

  • The persist() method will not execute an insert query if it is called outside of transaction boundaries. While, the save() method returns an identifier so that an insert query is executed immediately to get the identifier, no matter if it are inside or outside of a transaction.

  • The persist method is called outside of transaction boundaries, it is useful in long-running conversations with an extended Session context. On the other hand save method is not good in a long-running conversation with an extended Session context.

  • Fifth difference between save and persist method in Hibernate: persist is supported by JPA, while save is only supported by Hibernate.

You can see the full working example from the post Difference between save and persist method in Hibernate


Here is the difference:

  1. save:

    1. will return the id/identifier when the object is saved to the database.
    2. will also save when the object is tried to do the same by opening a new session after it is detached.
  2. Persist:

    1. will return void when the object is saved to the database.
    2. will throw PersistentObjectException when tried to save the detached object through a new session.

Actually the difference between hibernate save() and persist() methods depends on generator class we are using.
If our generator class is assigned, then there is no difference between save() and persist() methods. Because generator ‘assigned’ means, as a programmer we need to give the primary key value to save in the database right [ Hope you know this generators concept ] In case of other than assigned generator class, suppose if our generator class name is Increment means hibernate it self will assign the primary key id value into the database right [other than assigned generator, hibernate only used to take care the primary key id value remember], so in this case if we call save() or persist() method then it will insert the record into the database normally
But hear thing is, save() method can return that primary key id value which is generated by hibernate and we can see it by
long s = session.save(k);
In this same case, persist() will never give any value back to the client, return void.
persist() also guarantees that it will not execute an INSERT statement if it is called outside of transaction boundaries.
where as Save() INSERT happens immediately, no matter if you are inside or outside of a transaction.


Basic rule says that :

For Entities with generated identifier :

save() : It returns an entity's identifier immediately in addition to making the object persistent. So an insert query is fired immediately.

persist() : It returns the persistent object. It does not have any compulsion of returning the identifier immediately so it does not guarantee that insert will be fired immediately. It may fire an insert immediately but it is not guaranteed. In some cases, the query may be fired immediately while in others it may be fired at session flush time.

For Entities with assigned identifier :

save(): It returns an entity's identifier immediately. Since the identifier is already assigned to entity before calling save, so insert is not fired immediately. It is fired at session flush time.

persist() : same as save. It also fire insert at flush time.

Suppose we have an entity which uses a generated identifier as follows :

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

save() :

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is fired immediately as this statement is executed.
    session.getTransaction().commit();
    session.close();

persist() :

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is not guaranteed to be fired immediately. It may get fired here.
    session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
    session.close();

Now suppose we have the same entity defined as follows without the id field having generated annotation i.e. ID will be assigned manually.

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

for save() :

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

for persist() :

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

The above cases were true when the save or persist were called from within a transaction.

The other points of difference between save and persist are :

  1. save() can be called outside a transaction. If assigned identifier is used then since id is already available, so no insert query is immediately fired. The query is only fired when the session is flushed.

  2. If generated identifier is used , then since id need to generated, insert is immediately fired. But it only saves the primary entity. If the entity has some cascaded entities then those will not be saved in db at this point. They will be saved when the session is flushed.

  3. If persist() is outside a transaction then insert is fired only when session is flushed no matter what kind of identifier (generated or assigned) is used.

  4. If save is called over a persistent object, then the entity is saved using update query.


It completely answered on basis of "generator" type in ID while storing any entity. If value for generator is "assigned" which means you are supplying the ID. Then it makes no diff in hibernate for save or persist. You can go with any method you want. If value is not "assigned" and you are using save() then you will get ID as return from the save() operation.

Another check is if you are performing the operation outside transaction limit or not. Because persist() belongs to JPA while save() for hibernate. So using persist() outside transaction boundaries will not allow to do so and throw exception related to persistant. while with save() no such restriction and one can go with DB transaction through save() outside the transaction limit.

참고URL : https://stackoverflow.com/questions/5862680/whats-the-advantage-of-persist-vs-save-in-hibernate

반응형