Qual é a vantagem de persist () vs save () no Hibernate?


Respostas:


154

A partir desta postagem no fórum

persist()está bem definido. Torna uma instância transitória persistente. No entanto, não garante que o valor do identificador seja atribuído à instância persistente imediatamente, a atribuição pode ocorrer no momento da liberação. As especificações não dizem isso, que é o problema que tenho persist().

persist()também garante que não executará uma instrução INSERT se for chamada fora dos limites da transação. Isso é útil em conversas de longa duração com um contexto estendido de sessão / persistência.

Um método como persist()é necessário.

save()não garante o mesmo, ele retorna um identificador e, se um INSERT precisar ser executado para obter o identificador (por exemplo, gerador de "identidade", não "sequência"), esse INSERT acontece imediatamente, independentemente de você estar dentro ou fora de uma transação. Isso não é bom em uma conversa de longa duração com um contexto estendido de sessão / persistência.


44
para acrescentar mais do mesmo post, para reclamar: "Infelizmente, cinco anos depois, esse tópico ainda permanece como a única fonte clara de informações sobre esse assunto. A documentação do Hibernate, embora detalhada, é nula de todas as informações de uso, exceto as mais triviais. Por que o último post de christian não está na sessão javadoc é apenas mais um mistério da documentação do Hibernate. "
kommradHomer

você quer dizer que o método persist () tornará a entidade no estado desanexado e o save () no estado anexado?
11135 Rekinyz

2
Recentemente, usei salvar e persistir em um mapeamento bidirecional um para muitos. Eu descobri que salvar não é transmitido em cascata ao filho, ou seja, apenas o pai é salvo / inserido na tabela. No entanto, o persist persistiu na tarefa de salvar pai e filho em uma chamada. Estou usando um ID composto e não um ID gerado.
Arn-arn

68

Fiz uma boa pesquisa sobre o save () vs persist (), incluindo a execução na minha máquina local várias vezes. Todas as explicações anteriores são confusas e não estão corretas. Comparei o save () e o persist () abaixo após uma pesquisa completa.

Save()

  1. Retorna o ID gerado após salvar. Seu Serializabletipo de retorno.
  2. salve as alterações no banco de dados fora da transação.
  3. Atribui o ID gerado à entidade que você está persistindo
  4. Session.save () para um objeto desanexado criará uma nova linha na tabela.

Persist()

  1. Não retorna o ID gerado após salvar. Seu tipo de retorno nulo.
  2. Não salva as alterações no banco de dados fora da transação.
  3. Atribui generated idà entidade que você está persistindo
  4. session.persist()para um objeto desanexado será lançado, PersistentObjectExceptionpois não é permitido.

Todos estes são experimentados / testados Hibernate v4.0.1.


O ponto 3 para Save () e Persist () são mencionados, mas na verdade não são os mesmos. O método Persist () também salva as alterações no db fora da transação.
precisa saber é o seguinte

2
Quando testei após cometer a transação usando persistem valor método não é salvo DB
Laxminarayana Challagonda

Então # 1 e # 5 são a diferença real entre os dois? Se você precisar de um ID retornado ou de uma nova linha criada, use Save()?
user2490003

Como Save () # 3 é possível fora da transação
vikas singh 08/04

24

Fiz alguns testes simulados para registrar a diferença entre save()e persist().

Parece que esses dois métodos se comportam da mesma maneira ao lidar com a entidade transitória, mas diferem ao lidar com a entidade desanexada.

Para o exemplo abaixo, use EmployeeVehicle como uma Entidade com PK como vehicleIdum valor gerado e vehicleNamecomo uma de suas propriedades.

Exemplo 1: Lidando com objetos transitórios

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

Resultado:

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

Observe que o resultado é o mesmo quando você obtém um objeto já persistente e o salva

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

Repita o mesmo usando persist(entity)e resultará o mesmo com o novo ID (digamos 37, honda);

Exemplo 2: Lidando com objetos desanexados

// 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();

Resultado: você pode esperar que o Veículo com o ID: 36 obtido na sessão anterior seja atualizado com o nome "Toyota". Mas o que acontece é que uma nova entidade é salva no banco de dados com o novo ID gerado e o nome como "Toyota"

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

Usando persistir para persistir entidade desanexada

// (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();

Resultado:

Exception being thrown : detached entity passed to persist

Portanto, é sempre melhor usar Persist () em vez de Save (), pois save deve ser usado com cuidado ao lidar com o objeto Transient.

Nota importante: No exemplo acima, o valor da entidade veículo é um valor gerado, portanto, ao usar save () para persistir em uma entidade desanexada, o hibernate gera um novo ID para persistir. No entanto, se este pacote não for um valor gerado, isso resultará em uma exceção declarando a chave violada.


12

Esta pergunta tem algumas boas respostas sobre os diferentes métodos de persistência no Hibernate. Para responder sua pergunta diretamente, com save () a instrução insert é executada imediatamente, independentemente do estado da transação. Ele retorna a chave inserida para que você possa fazer algo assim:

long newKey = session.save(myObj);

Portanto, use save () se você precisar de um identificador atribuído à instância persistente imediatamente.

Com persist (), a instrução insert é executada em uma transação, não necessariamente imediatamente. Isso é preferível na maioria dos casos.

Use persist () se você não precisar que a inserção ocorra fora de sequência com a transação e não precise da chave inserida retornada.


6

Aqui estão as diferenças que podem ajudá-lo a entender as vantagens dos métodos persistir e salvar:

  • A primeira diferença entre salvar e persistir é o tipo de retorno. O tipo de retorno do método persistente é nulo, enquanto o tipo de retorno do
    método save é um objeto serializável.
  • O método persist () não garante que o valor do identificador seja atribuído ao estado persistente imediatamente; a atribuição pode ocorrer no momento da liberação.

  • O método persist () não executará uma consulta de inserção se for chamado fora dos limites da transação. Enquanto, o método save () retorna um identificador para que uma consulta de inserção seja executada imediatamente para obter o identificador, independentemente de estar dentro ou fora de uma transação.

  • O método persist é chamado fora dos limites da transação; é útil em conversas de longa duração com um contexto de Sessão estendido. Por outro lado, o método save não é bom em uma conversa de longa duração com um contexto de sessão estendido.

  • Quinta diferença entre o método save e persist no Hibernate: persist é suportado pelo JPA, enquanto o save é suportado apenas pelo Hibernate.

Você pode ver o exemplo completo de trabalho no post Diferença entre o método save e persist no Hibernate


Primeiro você diz "O método persist () não executará uma consulta de inserção se for chamada fora dos limites da transação". Então você diz "O método persistente é chamado fora dos limites da transação; é útil em conversas de longa duração com um contexto de Sessão estendido". Eles não são contraditórios? Eu não entendo
Kumar Manish

@KumarManish No caso do método persist, uma consulta de inserção acontece no momento da liberação. Por isso, é uma prática recomendada em conversas de longa duração #
David Pham

5

save () - Como o nome do método sugere, a hibernação save () pode ser usada para salvar a entidade no banco de dados. Podemos invocar esse método fora de uma transação. Se usarmos isso sem transação e tivermos uma cascata entre entidades, somente a entidade principal será salva, a menos que liberemos a sessão.

persist () - O hibernate persist é semelhante ao save (with transaction) e adiciona o objeto de entidade ao contexto persistente, para que quaisquer alterações adicionais sejam rastreadas. Se as propriedades do objeto forem alteradas antes da transação ser confirmada ou da liberação da sessão, ela também será salva no banco de dados. Além disso, podemos usar o método persist () apenas dentro dos limites de uma transação, por isso é seguro e cuida de qualquer objeto em cascata. Por fim, persist não retorna nada, portanto, precisamos usar o objeto persistente para obter o valor do identificador gerado.


5

Aqui está a diferença:

  1. Salve :

    1. retornará o ID / identificador quando o objeto for salvo no banco de dados.
    2. também será salvo quando o objeto for tentado fazer o mesmo, abrindo uma nova sessão depois de desanexada.
  2. Persistir:

    1. retornará nulo quando o objeto é salvo no banco de dados.
    2. lançará PersistentObjectException quando tentar salvar o objeto desanexado por meio de uma nova sessão.

Você pode mostrar um exemplo com um trecho? Isso seria útil.
precisa saber é o seguinte

5

A regra básica diz que:

Para entidades com identificador gerado:

save (): retorna o identificador de uma entidade imediatamente, além de tornar o objeto persistente. Portanto, uma consulta de inserção é acionada imediatamente.

persist (): retorna o objeto persistente. Ele não tem nenhuma compulsão em retornar o identificador imediatamente, portanto, não garante que a inserção seja acionada imediatamente. Pode disparar uma inserção imediatamente, mas não é garantido. Em alguns casos, a consulta pode ser acionada imediatamente, enquanto em outros pode ser acionada no momento da liberação da sessão.

Para entidades com identificador atribuído:

save (): retorna o identificador de uma entidade imediatamente. Como o identificador já está atribuído à entidade antes de chamar save, a inserção não é acionada imediatamente. É acionado no momento da liberação da sessão.

persist (): o mesmo que salvar. Ele também dispara a inserção no momento da descarga.

Suponha que tenhamos uma entidade que use um identificador gerado da seguinte maneira:

@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;
    }
}

Salve () :

    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();

persistir() :

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.persist(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();

Agora, suponha que tenhamos a mesma entidade definida a seguir, sem que o campo id tenha gerado anotação, ou seja, o ID será atribuído manualmente.

@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;
    }
}

para salvar ():

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();

para 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();

Os casos acima eram verdadeiros quando o salvamento ou a persistência eram chamados de dentro de uma transação.

Os outros pontos de diferença entre salvar e persistir são:

  1. save () pode ser chamado fora de uma transação. Se o identificador atribuído for utilizado, como o id já está disponível, nenhuma consulta de inserção será acionada imediatamente. A consulta é acionada apenas quando a sessão é liberada.

  2. Se o identificador gerado for usado, desde que o ID precise ser gerado, a inserção será acionada imediatamente. Mas ele salva apenas a entidade principal. Se a entidade tiver algumas entidades em cascata, elas não serão salvas no banco de dados neste momento. Eles serão salvos quando a sessão for liberada.

  3. Se persist () estiver fora de uma transação, a inserção será acionada apenas quando a sessão for liberada, independentemente do tipo de identificador (gerado ou atribuído) usado.

  4. Se save for chamado sobre um objeto persistente, a entidade será salva usando a consulta de atualização.


2

Na verdade, a diferença entre os métodos hibernate save () e persist () depende da classe do gerador que estamos usando.
Se nossa classe de gerador for atribuída, não haverá diferença entre os métodos save () e persist (). Como o gerador 'atribuído' significa, como programador, precisamos fornecer o valor da chave primária para salvar no banco de dados corretamente [Espero que você conheça esse conceito de geradores] No caso de uma classe geradora diferente da atribuída, suponha que se o nome da nossa classe de gerador for Incrementar O próprio hibernate atribuirá o valor do ID da chave primária no banco de dados à direita [exceto o gerador atribuído, o hibernate usado apenas para cuidar do valor do ID da chave primária, lembre-se], portanto, neste caso, se chamarmos o método save () ou persist (), então ele irá inserir o registro no banco de dados normalmente.
Mas aqui, o método save () pode retornar o valor do ID da chave primária que é gerado pelo hibernate e podemos vê-lo por
long s = session.save (k);
Nesse mesmo caso, persist () nunca devolverá nenhum valor ao cliente, retorne o tipo void.
O persist () também garante que não executará uma instrução INSERT se for chamada fora dos limites da transação.
enquanto em save (), INSERT acontece imediatamente, independentemente de você estar dentro ou fora de uma transação.


1

Respondeu completamente com base no tipo "gerador" no ID enquanto armazena qualquer entidade. Se o valor do gerador for "atribuído", significa que você está fornecendo o ID. Então, não faz diferença no hibernar para salvar ou persistir. Você pode usar qualquer método que desejar. Se o valor não for "atribuído" e você estiver usando save (), receberá o ID como retorno da operação save ().

Outra verificação é se você está executando a operação fora do limite da transação ou não. Porque persist () pertence ao JPA enquanto save () para hibernação. Portanto, o uso de persist () fora dos limites da transação não permitirá isso e gerará uma exceção relacionada ao persistente. enquanto com save () não existe essa restrição e é possível ir com a transação do banco de dados através de save () fora do limite da transação.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.