Hibernation fails by adding the fully qualified class name to the property name in the ManyToMany association

I'm trying to map two objects to each other using the ManyToMany association, but for some reason, when I use the mappedBy property, hibernate seems to be confused about what exactly I'm matching. The only difference in my comparison is that the association is not performed in the primary key field in one of the records (the field is unique, though).

Tables:

 Sequence ( id NUMBER, reference VARCHAR, ) Project ( id NUMBER ) Sequence_Project ( proj_id number references Project(id), reference varchar references Sequence(reference) ) 

Objects look (annotations are on the getter, put them in fields to condense the bit):

 class Sequence { @Id private int id; private String reference; @ManyToMany(mappedBy="sequences") private List<Project> projects; } 

And own side:

 class Project { @Id private int id; @ManyToMany @JoinTable(name="sequence_project", joinColumns=@JoinColumn(name="id"), inverseJoinColumns=@JoinColumn(name="reference", referencedColumnName="reference")) private List<Sequence> sequences; } 

This is not thrown using the MappingException:

property-ref [_test_local_entities_Project_sequences] not found on object [test.local.entities.Project]

It seems weird to add the fully qualified class name, separated by an underscore. How can i avoid this?

EDIT: I played a little with this. Changing the name of the mappedBy property raises another exception, namely:

org.hibernate.AnnotationException: mappedBy refers to an unknown property of the target: test.local.entities.Project.sequences

So, the annotation is processed correctly, but for some reason the reference to the property is incorrectly added to the internal configuration of Hibernate.

+7
java hibernate
source share
4 answers

I made the same scenario suggested by your question. And, as expected, I get the same exception. Like a complementary task, I made the same script , but with one-to-many many-to-one using a non-primary key as a concatenated column such as a link, I now

SecondaryTable JoinColumn cannot reference a non-primary key

Well, maybe this is a mistake? Well, yes (and your workaround works fine (+1)). If you want to use a non-primary key as a primary key , you must ensure that it is unique. Perhaps this explains why Hibernate does not allow the non-primary key to be used as the primary key (unrecognized users may get unexpected behavior).

If you want to use the same mapping, you can split @ManyToMany relationships by @ OneToMany-ManyToOne Using encapsulation , you don't need to worry about a merged class

Project

 @Entity public class Project implements Serializable { @Id @GeneratedValue private Integer id; @OneToMany(mappedBy="project") private List<ProjectSequence> projectSequenceList = new ArrayList<ProjectSequence>(); @Transient private List<Sequence> sequenceList = null; // getters and setters public void addSequence(Sequence sequence) { projectSequenceList.add(new ProjectSequence(new ProjectSequence.ProjectSequenceId(id, sequence.getReference()))); } public List<Sequence> getSequenceList() { if(sequenceList != null) return sequenceList; sequenceList = new ArrayList<Sequence>(); for (ProjectSequence projectSequence : projectSequenceList) sequenceList.add(projectSequence.getSequence()); return sequenceList; } } 

Sequence

 @Entity public class Sequence implements Serializable { @Id private Integer id; private String reference; @OneToMany(mappedBy="sequence") private List<ProjectSequence> projectSequenceList = new ArrayList<ProjectSequence>(); @Transient private List<Project> projectList = null; // getters and setters public void addProject(Project project) { projectSequenceList.add(new ProjectSequence(new ProjectSequence.ProjectSequenceId(project.getId(), reference))); } public List<Project> getProjectList() { if(projectList != null) return projectList; projectList = new ArrayList<Project>(); for (ProjectSequence projectSequence : projectSequenceList) projectList.add(projectSequence.getProject()); return projectList; } } 

Projectsequence

 @Entity public class ProjectSequence { @EmbeddedId private ProjectSequenceId projectSequenceId; @ManyToOne @JoinColumn(name="ID", insertable=false, updatable=false) private Project project; @ManyToOne @JoinColumn(name="REFERENCE", referencedColumnName="REFERENCE", insertable=false, updatable=false) private Sequence sequence; public ProjectSequence() {} public ProjectSequence(ProjectSequenceId projectSequenceId) { this.projectSequenceId = projectSequenceId; } // getters and setters @Embeddable public static class ProjectSequenceId implements Serializable { @Column(name="ID", updatable=false) private Integer projectId; @Column(name="REFERENCE", updatable=false) private String reference; public ProjectSequenceId() {} public ProjectSequenceId(Integer projectId, String reference) { this.projectId = projectId; this.reference = reference; } @Override public boolean equals(Object o) { if (!(o instanceof ProjectSequenceId)) return false; final ProjectSequenceId other = (ProjectSequenceId) o; return new EqualsBuilder().append(getProjectId(), other.getProjectId()) .append(getReference(), other.getReference()) .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder().append(getProjectId()) .append(getReference()) .hashCode(); } } } 
+3
source share

I finally figured it out, more or less. I think this is basically a sleep error.

edit: I tried to fix this by changing my own side of the association:

 class Sequence { @Id private int id; private String reference; @ManyToMany @JoinTable(name="sequence_project", inverseJoinColumns=@JoinColumn(name="id"), joinColumns=@JoinColumn(name="reference", referencedColumnName="reference")) private List<Project> projects; } class Project { @Id private int id; @ManyToMany(mappedBy="projects") private List<Sequence> sequences; } 

This worked, but caused problems elsewhere (see comment). So I refused and modeled the association as an organization with many associations in Sequence and Project. I think that this is at least a processing / failure error (the exception is not very appropriate, and the failure mode is simply incorrect) and will try to report this to the Hibernate developers.

+2
source share

IMHO what you are trying to achieve is not possible with JPA / Hibernate annotations. Unfortunately, the APIDoc JoinTable here is a bit unclear, but all the examples I found use primary keys when matching join tables.

We had the same problem as you in the project, where we also could not change the outdated database schema. The only viable option was dropping Hibernate and using MyBatis ( http://www.mybatis.org ), where you have the full flexibility of your own SQL to express more complex join conditions.

0
source share

I have run into this problem a dozen times already, and the only workaround I found is configuring @JoinTable twice with columns replaced on the other side of the relationship:

 class Sequence { @Id private int id; private String reference; @ManyToMany @JoinTable( name = "sequence_project", joinColumns = @JoinColumn(name="reference", referencedColumnName="reference"), inverseJoinColumns = @JoinColumn(name="id") ) private List<Project> projects; } class Project { @Id private int id; @ManyToMany @JoinTable( name = "sequence_project", joinColumns = @JoinColumn(name="id"), inverseJoinColumns = @JoinColumn(name="reference", referencedColumnName="reference") ) private List<Sequence> sequences; } 

I have not tried it yet with a column other than the primary key.

0
source share

All Articles