boutss
December 21, 2022, 11:25am
1
Hello,
I have a collection that has a return variable that can be of multiple types and therefore uses a ROLE (or D-TYPE) column.
For this return variable I cannot use @ManyToOne because it does not allow the use of ROLE columns.
So I use an @ANY
Everything works except that the ROLE column (here ELEMENTDETRAVAIL_ROLE) is not updated during the persisterCollection.
Do you have any idea how to handle this case?
Thanking you.
public class Agent implements IElementDeTravail
...
@OneToMany
@JoinColumn(name = "ELEMENTDETRAVAIL_ID")
private Set<Tache> taches = new HashSet<>();
public class Tache
....
@Any(metaDef = "IElementDeTravailMetaDef", metaColumn = @Column(name = "ELEMENTDETRAVAIL_ROLE"))
@JoinColumn(name = "ELEMENTDETRAVAIL_ID")
private IElementDeTravail elementDeTravail;
For information, we are migrating to hibernate 6.1.5 but I don’t think it changes much, except the @AnyValue and the metadef
22/12/2022 : small correction there was no mappedby which is not compatible with the @JoinColumn
beikov
December 21, 2022, 11:53am
2
boutss
December 21, 2022, 1:05pm
3
I do this as soon as possible. Thanks very much.
boutss
December 22, 2022, 4:43pm
4
In fact to be more precise the real problem is rather with the use of mappedBy (normal use).
And there it tells us the collection foreign key mapping has wrong number of column.
Logical because the primary key of Agent consists only of an ID column while the foreign key of two columns ID + ROLE
Caused by: org.hibernate.MappingException: collection foreign key mapping has wrong number of columns: org.hibernate.bugs.entity.Affaire.taches type: long
at org.hibernate.mapping.Collection.validate(Collection.java:379)
at org.hibernate.mapping.Set.validate(Set.java:51)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:380)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:301)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425)
I add the source code of the TU.
Do I still create a JIRA ticket?
boutss
December 22, 2022, 4:45pm
5
package org.hibernate.bugs.entity;
import java.util.Set;
import jakarta.persistence.*;
@Entity
@DiscriminatorColumn
@DiscriminatorValue("affaire")
public class Affaire implements IElementDeTravail {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "elementDeTravail", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Tache> taches;
public void setId(final Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public Set<Tache> getTaches() {
return taches;
}
public void setTaches(final Set<Tache> taches) {
this.taches = taches;
}
}
package org.hibernate.bugs.entity;
import jakarta.persistence.*;
import org.hibernate.annotations.*;
import org.hibernate.annotations.JavaType;
import org.hibernate.type.descriptor.java.*;
@Entity
public class Tache {
@Id
@GeneratedValue
private Long id;
@Any
@AnyDiscriminator(DiscriminatorType.STRING)
@AnyDiscriminatorValue(discriminator = "affaire", entity = Affaire.class)
@AnyKeyJavaClass(Long.class)
@Column(name = "ELEMENTDETRAVAIL_ROLE")
@JoinColumn(name = "ELEMENTDETRAVAIL_ID")
private IElementDeTravail elementDeTravail;
public void setId(final Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public IElementDeTravail getElementDeTravail() {
return elementDeTravail;
}
public void setElementDeTravail(final IElementDeTravail objetMaitre) {
this.elementDeTravail = objetMaitre;
}
}
package org.hibernate.bugs;
import java.util.Set;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import org.hibernate.Session;
import org.hibernate.bugs.entity.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* This template demonstrates how to develop a test case for Hibernate ORM, using the Java Persistence API.
*/
public class JPAUnitTestCase {
private EntityManagerFactory entityManagerFactory;
@Before
public void init() {
entityManagerFactory = Persistence.createEntityManagerFactory( "templatePU" );
}
@After
public void destroy() {
entityManagerFactory.close();
}
// Entities are auto-discovered, so just add them anywhere on class-path
// Add your tests, using standard JUnit.
@Test
public void hhh123Test() throws Exception {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
// Do stuff...
Affaire affaire = new Affaire();
final Set<Tache> taches = Set.of(new Tache(), new Tache());
affaire.setTaches(taches);
entityManager.persist(affaire);
entityManager.flush();
entityManager.clear();
// KO here
final Affaire affaireReload = entityManager.unwrap(Session.class).byId(affaire.getClass()).load(affaire.getId());
entityManager.getTransaction().commit();
entityManager.close();
}
}
beikov
December 23, 2022, 12:51pm
6
You’re not the first one to ask for this. You can track this issue: [HHH-15722] - Hibernate JIRA
boutss
December 23, 2022, 1:43pm
7
It’s actually the same issue.
I wait then, no need to recreate a JIRA ticket that would be duplicated.
Thanks to you