I have a composite key Resource_PK.class
I added it to the parent class Resource.class of my objects.
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Setter
@Embeddable
public class Resource_PK implements Serializable {
private UUID id;
private UUID partitionId;
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Resource_PK pk = (Resource_PK) o;
return Objects.equals( id, pk.partitionId ) &&
Objects.equals( id, pk.partitionId );
}
@Override
public int hashCode() {
return Objects.hash( id, partitionId );
}
}
@IdClass( Resource_PK.class)
@Getter
@Setter
public class Resource implements Serializable {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID",
strategy = "de.si.dynamobffdatasetup.tools.UUIDGenerator")
private UUID id;
// partitions are NOT generated, they are set
// they are part of the key, for performance reasons
@Id
private UUID partitionId;
I want to define a ManyToMany relationship from Equipment.class to self.
Equipment * -feeds-> * Equipment
@Entity
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Setter
@DiscriminatorValue("3")
public class Equipment extends Resource {
@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
private EquipmentType equipmentType;
@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
@JoinColumns({
@JoinColumn(
name = "isPartOfParent_id",
referencedColumnName = "id"),
@JoinColumn(
name = "isPartOfParent_partitionId",
referencedColumnName = "partitionId")
})
private Equipment isPartOfParent;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name="FeedsRel",
joinColumns={
@JoinColumn(
name = "feedsrel_id",
referencedColumnName = "id"),
@JoinColumn(
name = "feedsrel_partitionId",
referencedColumnName = "partitionId")
})
private Set<Equipment> feeds = new HashSet<Equipment>();
@ManyToMany( cascade = CascadeType.ALL, mappedBy="feeds", fetch = FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
private Set<Equipment> fedBy = new HashSet<Equipment>();
So I find 2 equipments, set their relationship, save.
// wire some equipment via feeds in a random partition
final Partition partition = d.randomPartition();
// find 2 equipments
Set<Equipment> eqs = equipmentRepository.getRandom(partition.getId(), 2);
Iterator<Equipment> iterator = eqs.iterator();
Equipment e1 = iterator.next();
Equipment e2 = iterator.next();
// add them to each other explicitely
e1.getFeeds().add(e2);
e2.getFedBy().add(e1);
equipmentRepository.saveAll(Arrays.asList(e1, e2));
But my problem is,
that I always get an error about a duplicate composite key of e1 when I try to save:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "equipment_pkey"
Detail: Key (id, partition_id)=(1e35ce1b-b2a4-49ff-b0ea-f8d66c76b16f, 424328b0-7953-48a9-9df9-7afd86600da8) already exists.
at app//org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675)
at app//org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365)
at app//org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355)
at app//org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490)
at app//org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408)
at app//org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:167)
at app//org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:135)
at app//com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at app//com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at app//org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
Question: How can I tell JPA and Spring, that this is an existing entity I save? So that it doesnt try to save the entity as new?
