hibernate. OneToOne mapping in database - java

I have following mapping:
#Entity
#Table(name="terminal_user")
public class TerminalUser {
#OneToMany(mappedBy="user",fetch = FetchType.LAZY)
private Set<UserContent> userContentSet;
....
}
#Entity
#Table(name="user_content")
public class UserContent {
#ManyToOne
#JoinColumn(name = "user_id")
TerminalUser user;
#OneToOne(mappedBy = "userContent")
Content content;
...
}
#Entity
#Table(name = "content")
public class Content {
#OneToOne
#JoinColumn(name = "user_content_id")
UserContent userContent;
....
}
After setting hibernate.hbm2ddl.auto to create
I see following database diagram:
For me relation of tables user_content and content is not one to one.
It looks same as relation of terminal_user and user_content and it is one to many
What do I wrong?

A unique constraint will make the difference:
#Entity
#Table(name = "content")
public class Content {
#OneToOne
#JoinColumn(name = "user_content_id", unique=true)
UserContent userContent;
....
}

Related

Problems with identifiing entity in another entity using Hibernate

Here is the code:
#Entity
#Table(name = "students")
public class BotUser {
...
#Id
#Column(name = "id", updatable = false)
private int id;
#OneToOne
private Equipment equipment;
...
}
#Entity
#Table(name = "students")
public class Equipment {
...
#Id
#Column(name = "id")
private int id;
...
}
When Hibernate is fetching equipment data from PostrgeSQL table, he requests "equipment_id" field, not "id". How to solve this problem?
I must use #JoinColumn annotation. And to be sure I added CascadeType.ALL
#Entity
#Table(name = "students")
public class BotUser {
...
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "id")
private Equipment equipment;
...
}
The same problem: AnnotationException Referenced property not a (One|Many)ToOne

JPA: Join particular column from another table

I want to join only one column from another table.
I have 2 entities now:
#Entity
public class Message {
....
#ManyToOne
#JoinColumn(name = "ATTRIBUTE_ID")
private Attribute attribute;
}
#Entity
#Table(name = "ATTRIBUTE_TABLE")
public class Attribute {
#Id
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
}
And I want to simplify code and don't use entity for only one column:
#Entity
#SecondaryTable(name = "ATTRIBUTE_TABLE", pkJoinColumns =
#PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "ATTRIBUTE_ID")),
public class Message {
....
#Column(table = "ATTRIBUTE_TABLE", name = "NAME")
private String attribute;
}
But #SecondaryTable JoinColumn cannot reference a non-primary key.
How to add a column from another table without using additional entity for it?

Ebean ManyToMany within Join Table?

I'm using ebean with play framework and I have a problem mapping a many-many relationship between 2 join tables. Let's say we have 3 entities, Person, Company, and Profession. A Person can have many Professions. A Person can work for many Companies. And a Company can employ many Persons in many Professions.
Here's my code:
#Entity
public class Company extends Model {
#Id
public Long id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
public List<CompanyPerson> companyPersons;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
public List<CompanyProfession> companyProfessions;
...
}
#Entity
public class Profession extends Model {
#Id
public Long id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "profession")
public List<CompanyProfession> companyProfessions;
...
}
#Entity
public class Person extends Model {
#Id
public Long id;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
public List<CompanyPerson> companyPersons;
...
}
#Entity
public class CompanyPerson extends Model {
#EmbeddedId
public CompanyPersonId id = new CompanyPersonId();
#ManyToOne
#JoinColumn(name = "company_id")
private Company company;
#ManyToOne
#JoinColumn(name = "person_id")
private Person person;
#ManyToMany(mappedBy = "companyPersons")
public List<CompanyProfession> companyProfessions;
...
}
#Entity
public class CompanyProfession extends Model {
#EmbeddedId
public CompanyProfessionId id = new CompanyProfessionId();
#ManyToOne
#JoinColumn(name = "company_id")
private Company company;
#ManyToOne
#JoinColumn(name = "profession_id")
private Person person;
#ManyToMany(cascade = CascadeType.ALL)
public List<CompanyPerson> companyPersons;
...
}
I get the following error:
Error injecting constructor, javax.persistence.PersistenceException: Error with the Join on [models.CompanyProfession.companyPersons]. Could not find the local match for [null] Perhaps an error in a #JoinColumn
at play.db.ebean.EbeanDynamicEvolutions.(EbeanDynamicEvolutions.java:36)
I tried adding JoinColumn(name = "companyperson_id") but that just changed the error from [null] to [companyperson_id].
Not sure what to do here. Any help?

JPA mapping annotation error org.hibernate.MappingException: Foreign key must have same number of columns as the referenced primary key

I can't propper map DB tables with JPA annotation.
Tables Subject and Place is ManyToMany through JoinTable.
Subject.java
#Entity
#Table(name = "SUBJECT")
public class Subject implements Serializable {
#Id
#Column(name = "SID")
private Integer sid;
#Column(name = "NAME")
private String name;
// getters and setters
}
SubjectPlace.java
#Entity
#Table(name = "SUBJECT_PLACE")
public class SubjectPlace implements Serializable {
#Id
#Column(name = "SPID")
private Integer spid;
#ManyToOne
#JoinColumn(name = "SUB_KEY") //Subject FK
private Subject subject;
#ManyToOne
#JoinColumn(name = "PLC_KEY") //Place FK
private Place place;
// getters and setters
}
Place.java
#Entity
#Table(name = "PLACE")
public class Place implements Serializable {
#Id
#Column(name = "PID")
private Integer pid;
#Column(name = "NAME")
private String name;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "SUBJECT_PLACE",
joinColumns = { #JoinColumn(name = "PLC_KEY", nullable = false, updatable = false) },
inverseJoinColumns = { #JoinColumn(name = "SUB_KEY", nullable = false, updatable = false) })
private Set<Subject> subjects;
// getters and setters
}
But than I need to link Person with Subject in selected Places. I mean that each Place has its own collection of Subject. And a Person have link to Subject whitch resides in particular Place.
like This:
Subject (M) -- (M) Place through JoinTable Subject (1) -- (M) Subject_Place (M) -- (1) Place
Person (M) -- (M) Subject_Place through JoinTable Person (1) -- (M) Person_Subject_Place (M) -- (1) Subject_Place
Person.java
#Entity
#Table(name = "PERSON")
public class Person implements Serializable {
#Id
#Column(name = "PRSID")
private Integer prsid;
#Column(name = "NAME")
private String name;
// How to annotate this code?
// I experience problem in this part of code
#OneToMany
#JoinColumn(name="SPID_KEY")
private List<SubjectPlace> subjectPlaces;
// getters and setters
}
PersonSubjectPlace.java
#Entity
#Table(name = "PERSON_SUBJECT_PLACE")
public class PersonSubjectPlace implements Serializable {
#Id
#Column(name = "PSPID") // Person_Subject_Place ID
private Integer pspid;
#ManyToOne
#JoinColumn(name = "PER_KEY") //Person FK
private Person person;
// How to annotate this code?
// I experience problem in this part of code
#ManyToOne
#JoinColumn(name = "SPID_KEY") //Subject_Place FK
private SubjectPlace subjectPlace;
// getters and setters
}
And when I try so get Persons and its Subjects, I get this error:
Caused by: org.hibernate.MappingException: Foreign key (FK2C3B79384AABC975:PERSON_SUBJECT_PLACE [SPID_KEY])) must have same number of columns as the referenced primary key (SUBJECT_PLACE [PLC_KEY,SUB_KEY])
What, How shoul I map?
In your OneToMany mapping you don't need to specify the foreign key, you just need to use mappedBy property to refer your mapping object, you can learn more about it in OneToMany Mapping Documentation, and here's what you need to map Person and PersonSubjectPlace entities:
In your Person class:
#OneToMany(mappedBy="person")
private List<PersonSubjectPlace> personsubjectPlaces;
In your PersonSubjectPlace class:
#ManyToOne
#JoinColumn(name="PRSID") //Specify the primary key of Person
private Person person;
For further information about the difference between JoinColumn and mappedBy you can take a look at this answer.
EDIT:
For the mapping between SubjectPlace and PersonSubjectPlace:
In your SubjectPlace class:
#OneToMany(mappedBy="subjectPlace")
private List<PersonSubjectPlace> personsubjectPlaces;
In your PersonSubjectPlace class:
#ManyToOne
#JoinColumn(name="SPID") //Specify the primary key of SubjectPerson
private SubjectPlace subjectPlace;
Note:
The best approach to map those classes is to use #JoinTable between Person and SubjectPlace, take a look at this #JoinTable example, because PersonSubjectPlace is pratically an asociation-entity between Person and SubjectPlace.
You should remove #Joincolumn annotation and add mappedBy variable to #OneToMany annotation.
#OneToMany(mappedBy = "spid")
You should have a variable in SubjectPlace that has a Person where you should put #JoinColumn annotation

Hibernate many to many mapping, join table with PK and extra columns

I've done the necessary changes to my models outlined here. However, I don't know what to put on my join table entity.
Note that my join table has a surrogate key , and two extra columns (date and varchar).
What I've got so far is:
User.java
#Entity
#Table (name = "tbl_bo_gui_user")
#DynamicInsert
#DynamicUpdate
public class User implements Serializable {
private String id;
private String ntName;
private String email;
private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
// Constructors and some getters setters omitted
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user", cascade=CascadeType.ALL)
public Set<GroupUser> getGroupUsers() {
return groupUsers;
}
public void setGroupUsers(Set<GroupUser> groupUsers) {
this.groupUsers = groupUsers;
}
}
Group.java
#Entity
#Table (name = "tbl_bo_gui_group")
#DynamicInsert
#DynamicUpdate
public class Group implements Serializable {
private String id;
private String groupName;
private String groupDesc;
private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
// Constructors and some getters setters omitted
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.group", cascade=CascadeType.ALL)
public Set<GroupUser> getGroupUsers() {
return groupUsers;
}
public void setGroupUsers(Set<GroupUser> groupUsers) {
this.groupUsers = groupUsers;
}
}
The problem is that I don't know what to put on my join table entity. Here it is.
GroupUser.java
#Entity
#Table (name = "tbl_bo_gui_group_user")
#DynamicInsert
#DynamicUpdate
#AssociationOverrides({
#AssociationOverride(name = "pk.user",
joinColumns = #JoinColumn(name = "id")),
#AssociationOverride(name = "pk.group",
joinColumns = #JoinColumn(name = "id")) })
public class GroupUser implements Serializable {
private String id;
private User userId;
private Group groupId;
private Date dateCreated;
private String createdBy;
// constructors and getters and setters for each property
// What now? ? No idea
}
user to group would be a Many-To-Many relation. Now, you are splitting that up into Two One-To-Many Relations. Therefore your Mapping Entity simple needs to complete the Many-To-Many relation, by using Many-To-One:
public class GroupUser implements Serializable {
private String id;
#ManyToOne
private User userId;
#ManyToOne
private Group groupId;
private Date dateCreated;
private String createdBy;
}
See also this example: Mapping many-to-many association table with extra column(s) (The Answer with 38 upvotes)

Categories