0

Trying to create a many-to-many relationship using Java Persistence annotations for the first time.

Scenario: Java class Project contains subprojects, which is just a List of Projects. There is no inverse (no superproject) member. So I thought the many-to-many relationship would be perfect for this

@ManyToMany(fetch = FetchType.EAGER, targetEntity = ProjectEntity.class, mappedBy = "project")    
@Override
public List<ProjectImpl> getSubProjects() {
    return super.getSubProjects();
}

Q1: Is this the correct way to persist a project with a list of subprojects?

Q2: Also, i am currently getting the error: mappedby reference an unknown target property. I found this highly rated thread for the error: mappedBy reference an unknown target entity property however i don't have a one one-to-many / many-to-one inverse or two different classes here

Edit: Based on Feedback, i changed the relation to one-to-many and added a JoinTable annotation based on the example in https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#entity-mapping-association-collections . However i get the error A Foreign key refering de.otsd.worklog.database.ProjectEntity from de.otsd.worklog.database.ProjectEntity has the wrong number of column. should be 2)

@OneToMany(fetch = FetchType.EAGER, targetEntity = ProjectEntity.class)    
@JoinTable(
        name = "ProjectToSubproject",
        joinColumns = @JoinColumn(name = "project_id"),
        inverseJoinColumns = @JoinColumn(name = "subproject_id")
)
@Override
public List<ProjectImpl> getSubProjects() {
    return super.getSubProjects();
}

@EmbeddedId
@Override
public ProjectKey getProjectKey() {
    return new ProjectKeyEntity(super.getProjectKey());
}
ptstone
  • 478
  • 7
  • 17
  • How is it many-to-many? Can one subproject belong to multiple projects? – Robby Cornelissen Aug 22 '19 at 05:05
  • Yes. Its a fringe case, but i don't want to exclude the possiblity (e.g. the subproject is billed & used by two different superprojects) – ptstone Aug 22 '19 at 05:14
  • 1
    However, that option isn't be very important to me if `@OneToMany` would be strictly superior here: that fringe case didn't happen so far in the real projects – ptstone Aug 22 '19 at 05:23
  • You have to decide whether you want to support this case. It would require some features and additional complexity. – Stefan Steinegger Aug 22 '19 at 07:25
  • 1
    You should **either** user one-to-many **or** use a join table for many-to-many. ont-to-many means that the subprojects get a foreign key in the table to reference the parent. Because they can only store one table in that field, it's **one**-to-many. On the other hand, many-to-many uses a join table that stores pairs of a parent-key and a subproject-key, thus able to store the same subproject with multiple parents. one-to-many and many-to-many refer to the relational representation of the data (not the OO represe – Stefan Steinegger Aug 27 '19 at 09:52
  • 1
    Your error massage most probably means that your db schema does not match the mapping. When you change the mapping, you need to change or re-create the database schema. – Stefan Steinegger Aug 27 '19 at 09:53
  • Thank you, i removed the join table and changed the get/setter to take/return project entities and finally got it to work. But your help certainly put me on the right path. – ptstone Aug 28 '19 at 16:28

1 Answers1

1

I guess you don't need mappedby at all, because it is not bi-directional. You probably should specify the link table that is used for the many-to-many (unless you change it to one-to-many).

Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
  • Hm, when i change the annotation to `@ManyToMany(fetch = FetchType.EAGER, targetEntity = ProjectEntity.class)` and keep everything else the same, i get a ton of warnings e.g. `WARN: GenerationTarget encountered exception accepting command: Error executing DDL " alter table project_project drop foreing key FK4..." via JDBC Statement` - is there anything else i need to do as well? – ptstone Aug 22 '19 at 11:46
  • 1
    You should specify the link table. When "mappedBy" is there, it assumes that it is the inverse relation and that the "real" relation is specified on a field on the other side. But in your case, you have to specify it right here. – Stefan Steinegger Aug 22 '19 at 12:15
  • 1
    By the way, how do the database tables look like and are they created by hibernate schema export or manually? – Stefan Steinegger Aug 22 '19 at 12:16
  • Update main post with `@JointTable` based on this documentation https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#entity-mapping-association-collections and i use hilbernate to create all tables – ptstone Aug 22 '19 at 13:00