'Merging entity with a unique constraint

I have an entity similar to:

@Entity
@Table( name="marchi", uniqueConstraints=@UniqueConstraint(columnNames="codice") )
public class Marchio implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    private String codice;

    private String nome;
//...
}

I create a Marchio with codice = 123, then I persist it. OK!

Then I retrieve it from the DB via a query, edit the "nome" property with something and call merge(). OK!

Then I create another Marchio with codice = 123. I put something in nome and call merge().

Result is:

ConstraintViolationException: Duplicate entry '123' for key 'codice'

Good, actually I can use the first way: query, edit property nome and merge.

Consider I don't have only "nome". I have 35 different properties, so I don't want to:

Marchio m = em.findCodice("123");
m.setP1("1");
m.setP2("2");
...
m.setPN("N");
em.merge(m); 

How can I do?



Solution 1:[1]

In spring data, you can simply

myRepository.save(entity)

Solution 2:[2]

The main intention of the merge method is to update a persistent entity instance with new field values from a detached entity instance. Firs of all, we need to get a persistent entity instance from a persistence context and update its fields with new values from this detached instance. So the merge method does exactly that: finds an entity instance by id taken from the passed object (either an existing entity instance from the persistence context is retrieved, or a new instance loaded from the database) copies fields from the passed object to this instance returns a newly updated instance. When you do that: "Then I create another Marchio with codice = 123" you create a new Marchio in transient state (without id). New Marchio it`s diferent Marchio then in database. For new Marchio in transient state operation MERGE do sql insert. For old Marchio in persistent state operation MERGE do sql update. For Insert you have a unique constraint. Here is the exception from the database. First of all, get the Marchio from the base ( find() or getReference() ). Then change the fields in it(Persistent Marchio) and then call MERGE. All this should be one unit of work (one transaction).

Solution 3:[3]

Try this:

@Table(name = "marchi", uniqueConstraints={@UniqueConstraint(columnNames="codice"), @UniqueConstraint(columnNames="nome")})

I believe with the above you can have:

codice nome
123     A
123     B
123     C

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 serv-inc
Solution 2 Andrew Dark
Solution 3 Sam I am says Reinstate Monica