Eu desconfio que essa seja uma pergunta de resposta muito simples, porém para mim, ela é necessária.
Estou fazendo as primeiras utilizações do JPA e não consegui entender a diferença entre esses dois métodos do EntityManager.
Qual deles faz realmente UPDATE no Banco de Dados?
Caso os dois façam UPDATE, por que existem os dois?
Agora a coisa complicou um pouco mais pra mim.
Criei três classes:
Usuario
Armamento
Cautela
Uma cautela é a união de um usuário com vários armamentos, além da data da cautela e um flag que condiciona se a cautela está aberta ou não.
Para tanto essa é a cara da Cautela
@Entity
public class Cautela {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToOne
private Usuario usuario;
@OneToMany
private Collection<Armamento> materiaisCautelados;
@Temporal(TemporalType.TIMESTAMP)
private Date dataCautela;
@Temporal(TemporalType.TIMESTAMP)
private Date dataEntrega;
private boolean opened;
Tentei persistir de várias formas uma cautela, consegui de duas formas:
Criava uma cautela, atribuía-lhe os objetos Usuario e a lista de Armamento e persistia-os em cascata (com CascadeType.PERSIST) de uma só vez.
Porém dessa forma não é interessante, pois é contrária à regra de negócio do meu sistema, pois os Usuarios e os Armamentos são persistidos individualmente antes de qualquer cautela.
consegui com em.merge(Cautela c).
Eu sou muito preocupado com o porquê das coisas e já estava intrigado com a diferença entre merge() e refresh() e agora mais essa.
Isso é culpa desses tutoriais que cobrem os assuntos de forma muito superficial.
Ex:
Para persistir um objeto ‘o’ no banco de dados usando JPA, basta fazer
em.persist(o)
O método refresh() atualiza o estado da instância a partir do banco de dados. Trocando em miúdos, copia os dados do banco e joga nos atributos da instância.
O método merge() atualiza a instância no banco de dados, transferindo seu estado para o banco. Ou seja, quem realmente faz update é o método merge().
A única semelhança entre o comportamento dos dois métodos é que ambos tornam a instância managed, significando que seu estado está sincronizado com o contexto de persistência.
Talvez seja hora de rever suas fontes. Estude a documentação de referência do Hibernate.
Sobre as minhas fontes, você há de convir que não existe um CREDIBILIDADÔMETRO pra me ajudar a escolher as mais confiáveis.
E também tenho uma pergunta.
Eu estou usando JPA e não Hibernate. A documentação do Hibernate me ajuda mesmo assim?
E sobre o persist e o merge?
Os dois salvam objetos no BD.
[quote=tnaires]A única semelhança entre o comportamento dos dois métodos é que ambos tornam a instância managed, significando que seu estado está sincronizado com o contexto de persistência.
[/quote]
Isso mesmo!
So lembrando um detalhe técnico: o merge devolve um objeto managed a partir de um objeto (que pode estar managed ou nao), que é diferente de tornar a instancia em managed. Por isso que o merge devolve T (esse sim é managed). O refresh nao aceita objetos detached, só managed. Algumas implementações fazem algo um pouquinho diferente (hibernate deixa dar refresh em detached, mas a especificação não).
Ajuda sim, para Hibernate veja a referência do Hibernate Core. Para JPA veja a referência dos módulos Annotations e EntityManager.
[quote=Cocota]E sobre o persist e o merge?
Os dois salvam objetos no BD.[/quote]
O persist() recebe uma instância no estado transient e a torna persistente - consequentemente managed. Ou seja, para inserir dados use persist().
Exato. Se você tem uma instância detached e quer torná-la managed, merge() é o método correto a se usar.