Duvidas Merge ou saveOrUpdate

11 respostas
K

E ai galera!

Estou com uma duvida qual é a diferença entre os métodos merge e saveOrUpdate

e em que ocasião cada um seria melhor aplicado?

11 Respostas

visola

Tem alguns posts que já discutiram isso por aqui:

http://www.guj.com.br/java/111501-jpa—saveorupdate
e
http://www.guj.com.br/java/146330-merge-jpa

emmanuelrock

De acordo com o livro Java Persistence com Hibernate, o método merge() religa um objeto contido no contexto de persistência. Acho que o desempenho usando este método é melhor, mas depende do cenário, não estou com o livro em mãos mas dê uma olhada aqui http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/

K

vlw..

Estou com outra duvida. eu possuo as seguintes classes Cliente
@Entity
@Table(name="Cliente", schema="Tecnicos")
@SequenceGenerator(name="SEQ_CLI", sequenceName="SEQ_CLIENTE", allocationSize=1, initialValue=1)

public class Cliente implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CLI")
    @Column(name="cli_id", nullable=false)
    @Resolvable(colName="ID")
    private Integer id;

    @Column(name="cli_codext")
    @Resolvable(colName="CÓDIGO")
    private Integer codigoExterno;

    @Column(name="cli_fili")
    @Resolvable(colName="FILIAL")
    private Integer filial;

    @Column(name="cli_razaosocial", length=80)
    @Resolvable(colName="RAZÃO SOCIAL")
    private String razaoSocial;

    @Column(name="cli_nomefantasia", length=80)
    @Resolvable(colName="NOME FANTASIA")
    private String nomeFantasia;

    @Column(name="cli_cnpj", length=20)
    private String cnpj;

    @Column(name="cli_inscest", length=30)
    private String InscEst;

    @Column(name="cli_endereco", length=200)
    private String endereco;

    @Column(name="cli_bairro", length=45)
    private String bairro;

    @Column(name="cli_cidade", length=50)
    private String cidade;

    @Column(name="cli_estado", length=2)
    private String estado;

    @Column(name="cli_cep", length=20)
    private String cep;

    @Column(name="cli_telefone", length=20)
    @Resolvable(colName="TELEFONE")
    private String telefone;

    @Column(name="cli_situreg", length=20)
    private String situ_reg;
    
    @Column(name="cli_emailPrincipal", length=150)
    @Resolvable(colName="EMAIL")
    private String emailPrincipal;

    @OneToMany(mappedBy="cliente", fetch=FetchType.LAZY)
    @Cascade(CascadeType.ALL)
    private Collection<EmailCliente> email;

   /* @ElementCollection
    @JoinTable(name="cli_email", joinColumns=@JoinColumn(name="cli_id "))
    @Column(name="cli_email_email")
    @IndexColumn(name="cli_email_id")
    private List<String> emails;
*/
    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(name="tecnico_cliente", schema="Tecnicos",
            joinColumns=@JoinColumn(name="teccli_cli_id"),
            inverseJoinColumns=@JoinColumn(name="teccli_tec_id"))
    private Collection<Tecnicos> tecnicos;

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(name="questionario_cliente", schema="Tecnicos",
            joinColumns=@JoinColumn(name="cli_id"),
            inverseJoinColumns=@JoinColumn(name="ques_id"))
    private Collection<Questionario> questionarios;
EmailCliente
@Entity
@Table(name="cli_email", schema="Tecnicos")

public class EmailCliente implements Serializable {

    @Id
    @Column(name="cli_email_id")
    @Resolvable(colName="ID")
    private Integer id;

    @Column(name="cli_email_email", nullable=false)
    @Resolvable(colName="EMAIL")
    private String email;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="cli_id", insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.SAVE_UPDATE)
    @Resolvable(colName="CLIENTE")
    private Cliente cliente;
E ClienteEmailPK
@Embeddable
public class ClienteEmailPK implements Serializable{

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="cli_email_cli_id", insertable=true, updatable=true)
    @Fetch(FetchMode.JOIN)
    @Cascade(CascadeType.SAVE_UPDATE)
    private Cliente cliente;

    @OneToMany(mappedBy="cliente", fetch=FetchType.LAZY)
    @Cascade(CascadeType.ALL)
    private EmailCliente emailCliente;

não estou conseguindo utilizar como chave composta em EmailCliente e tambem não sei se a minha classe ClienteEmailPk esta certo.

visola

Quando você vai usar uma classe como Embedded não precisa usar os relacionamentos one-to-many e many-to-one. O JPA vai mapear isso tudo para você.

Só precisa colocar na classe que será a PK a anotação IdClass. Tem um exemplo na documentação.

No site do OpenJPA também tem isso bem explicado: http://openjpa.apache.org/builds/apache-openjpa-1.3.0-SNAPSHOT/docs/manual/manual.html#jpa_overview_mapping_embed

K
entao minha classe pk ficaria assim?
@Embeddable
public class ClienteEmailPK implements Serializable{

    
    private Cliente cliente;

    private EmailCliente emailCliente;
e a EmailCliente
@Entity
@Table(name="cli_email", schema="Tecnicos")

public class EmailCliente implements Serializable {

    @EmbeddedId
    private ClienteEmailPK id;
    
    @Column(name="cli_email_email", nullable=false)
    @Resolvable(colName="EMAIL")
    private String email;
e a Cliente da mesma forma?
visola

Desculpa ksio_thadeu… não sei se entendi o que você está fazendo. Quer relacionar a classe cliente com a email, é isso? Ou quer usar como chave primária do Email o id do cliente também?

Por que está colocando dentro do sua EmailClientePK uma instância de cliente e outra de EmailCliente? Se for porque existe uma tabela de relacionamento, ela tem que ser mapeada no relacionamento e não numa outra classe.

K

O que eu estou querendo fazer e o seguinte

eu possuo as classe cliente e email,
um cliente pode ter mais de um email,
eu queria que fosse criado uma chave primaria composta do id do email + o codigo do cliente,
pois assim eu poderia fazer o exemplo:
Cliente 1 emails(1,2,3) outro cliente: cliente2 emails(1,2)
e no banco ficasse assim:
|id_email |email |cli_id|

|1 |teste | 1 |
|2 |teste | 1 |
|3 |teste | 1 |

|1 |teste | 2 |
|2 |teste | 2 |

visola

Então… não precisa fazer uma classe de PK. O Hibernate vai tomar conta disso para você. Quando você diz que tem um relacionamento ManyToOne e OneToMany e usa o MappedBy do jeito que você usou, está dizendo para a o Hibernate que na tabela de email vai ter o id do cliente - mais especificamente na coluna “cli_id”. Ou seja, vai ficar do jeito que você quer.

K

Sim. mais por exemplo, eu tenho os emails 1,2 para o cliente1
e tento inserir os emails 1,2,3 para o cliente 2

o que acontece é que como eu defini que o id é o cli_email_id ex: os emails 1,2 do cliente 1, sao atualizados,
ao inves de ser inseridos, por isso eu pensei na solução de criar um classe que represente um chave composta.

Existe alguma outra solução para o meu problema???

visola

Se você passar um email com cli_email_id 0 (zero), ele deve inserir um novo registro. Não? Você fez o teste?

K

se eu setar o id do email com zero ele insere normal pois a minha sequencia de ids inicia em 1, mais quando eu for inserir outro email
por e o id ja existir no banco mesmo que seja para outro cliente ele atualiza o registro que ja existe no banco ao inves de inserir.

Criado 24 de fevereiro de 2011
Ultima resposta 24 de fev. de 2011
Respostas 11
Participantes 3