| Hi there, Sometimes there is a need to make a non-standard association between two entities. Imagine this example:
create table person (
id bigint generated by default as identity,
first_name varchar(255),
last_name varchar(255),
primary key (id)
);
create table alternative_name (
id bigint generated by default as identity,
alternative varchar(255),
name varchar(255),
primary key (id)
);
insert into person (first_name,last_name) values ('blazej', 'adamczyk');
insert into person (first_name,last_name) values ('blazej', 'testing');
insert into alternative_name (name, alternative) values ('blazej', 'blaze');
insert into alternative_name (name, alternative) values ('blazej', 'vlach');
A person has first and last name. Multiple Person can have the same name, and a single name may have multiple alternative_names. Thus we have a ManyToMany but without a jointable. It is possible to do this using a single sided OneToMany collection on Person class like this:
@Entity
@Data
@ToString
@NoArgsConstructor
public class Person implements Serializable {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
@OneToMany
@JoinColumn(name="name", referencedColumnName = "firstName")
List<AlternativeName> alternativeNameList;
}
This works well until we do not fetch several Persons with the same first_name during a single transaction. If this happens during flush and commit we get the following:
org.hibernate.HibernateException: Found shared references to a collection
After digging a bit through the hibernate classes I found that the CollectionKey which identifies a collection between the two classes is based only on the "JoinColumn". I would like to start a discussion: Could we identify a PersistenceCollection by the "JoinColumn" but additionally by the PK of the source object? This way in the above example both Person will get a new collection representing alternative names but not the same. There's the problem of updating these collections of course. Maybe we can assume that if the "One" side is not actually really one, than the user should be aware of what he is doing and will not modify this collection in multiple objects? Alternatively maybe this check for shared collections should be disabled if the collections are marked non insertable and non updateable? This should still leave the users the ability to properly handle such association at least in read only mode. In the attachment I have uploaded a zip containg a spring-boot project showing the error and a "proposed" (probably wrong) solution by modifying the CollectionReferenceInitializerImpl and CollectionKey classes. Let me know what you think about this. Thanks. |