I am new in Hibernate association mapping. When I tried to implement a small mapping logic all the previous foreign key is automatically update to Null
File Employee.java
#Entity
public class Employee extends CommonFields implements Serializable {
private static final long serialVersionUID = -723583058586873479L;
#Id
#Column(name = "id", insertable = false, updatable = false)
#GeneratedValue
private Long id;
private String employeeName;
#OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
#JoinColumn(name = "emp_id", referencedColumnName = "id")
private List<Education> education;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public List<Education> getEducation() {
return education;
}
public void setEducation(List<Education> education) {
this.education = education;
}
}
File Education.java
#Entity
public class Education extends CommonFields implements Serializable {
public Education() {
}
private static final long serialVersionUID = -723583058586873479L;
#Id
#Column(name = "id", insertable = false, updatable = false)
#GeneratedValue
private Long id;
private String course;
#ManyToOne
#JoinColumn(name = "emp_id")
private Employee employee;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
Please anyone suggest a solution. I really stuck on this part last two days.
Related
I have a Spring Boot 2.1.13 (Java 8) project with MySQL 8.0.21 and mysql-connector-java version: 8.0.22 with the following classes.
#Entity
#Table(name = "user")
#JsonIgnoreProperties({"type", "location", "hibernateLazyInitializer", "handler"})
public class User implements java.io.Serializable {
private UserType userType;
private Location location;
private long id;
private String name;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "usertypeid")
public UserType getUserType() {
return this.userType;
}
public void setUserType(UserType userType) {
this.userType = userType;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "locationid", nullable = false)
public Location getLocation() {
return this.location;
}
public void setLocation(Location location) {
this.location = location;
}
#Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "usertype")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class UserType implements java.io.Serializable {
private long id;
private String name;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "location")
public class Location implements java.io.Serializable {
private long id;
private String name;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
I fetch the user record using the following code
User user = userRepository.findById(userId).orElse(null);
Now when I try to fetch the UserType object from my user object, I don't get any values, except the ID. For example, when I run the following command, it gives me a null value
user.getUserType().getName()
However, when I run the following code, I get the expected not null value.
user.getLocation().getName()
Both userType and location are lazy-loaded, however, the values of only location are available in the code.
I have checked the values in DB tables. They are not null for both user type and location.
I have checked the values in the debugger as well. The Location object seems to be a proxy, however, the UserType not a hibernate proxy object. I am not sure if this is an issue.
I have used spring boot with hibernate. And swagger to generate the dtos and the api interface.
There are two entities. The project entity is the parent and application entity is the child. Have create a onetomany relationship. But when i try to persist. I see not applications getting added for a project.
Project Entity:
#Entity
#Table(name="ProjectEntity")
public class ProjectEntity {
#Id
#Column(name = "ProjectGuid", length = 36, nullable = false, unique = true)
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(name = "Name")
private String name;
#OneToMany(mappedBy="projectApp", cascade = CascadeType.ALL)
private List<ApplicationEntity> apps=new ArrayList<>();
public ProjectEntity() {
}
public ProjectEntity(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ApplicationEntity> getApps() {
return apps;
}
public void setApps(List<ApplicationEntity> apps) {
this.apps = apps;
}
}
Application Entity:
#Entity
#Table(name="ApplicationEntity")
public class ApplicationEntity {
#Id
#Column(name = "Name", length = 36, nullable = false, unique = true)
private String name;
private String repositoryUrl;
#ManyToOne
#Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
#JoinColumn(name = "ProjectGuid")
private ProjectEntity projectApp;
public ApplicationEntity() {
}
public ApplicationEntity(String name, String repositoryUrl) {
this.name = name;
this.repositoryUrl = repositoryUrl;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRepositoryUrl() {
return repositoryUrl;
}
public void setRepositoryUrl(String repositoryUrl) {
this.repositoryUrl = repositoryUrl;
}
public ProjectEntity getProjectApp() {
return projectApp;
}
public void setProjectApp(ProjectEntity projectApp) {
this.projectApp = projectApp;
}
}
Controller operation:
ProjectEntity project = projectService.getProject(projectName);
List<ApplicationEntity> appList = new ArrayList<>();
ApplicationEntity appEntity = new ApplicationEntity(app.getName(), app.getRepositoryUrl());
applicationRepository.save(appEntity);
appList.add(appEntity);
project.setApps(appList);
projectRepository.save(project);
You need to set the id of the ProjectEntity on the owning side (which is the ApplicationEntity)
appEntity.setProjectApp(project);
Otherwise hibernate (and your database) does not know to which parent a ApplicationEntity belongs.
Here is an example many to one relation with spring data jpa :
#Data
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
}
#Data
#Entity
public class Question extends BaseEntity{
private String questionText;
private int anketId;
private int subjectId;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "question")
List<Answer> answers;
}
#Data
#Entity
public class Answer extends BaseEntity{
private String answerText;
private String code;
private int score;
private int priority;
private boolean isValidAnswer;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "question_id", referencedColumnName = "id", insertable = false, updatable = false)
private Question question;
}
#DataJpaTest
public class QuestionRepositoryTest {
#Autowired
TestEntityManager entityManager;
#Autowired
QuestionRepository sut;
#Test
public void it_should_create_question_wiht_answers() {
Question question = new Question();
question.setSubjectId(1);
question.setAnketId(1);
question.setQuestionText("test question");
Answer answer = new Answer();
answer.setAnswerText("answer");
answer.setCode("1a");
answer.setPriority(0);
answer.setValidAnswer(true);
question.setAnswers(Arrays.asList(answer));
entityManager.persistAndFlush(question);
List<Question> questionList = sut.findAll();
assertThat(questionList).containsExactly(question);
assertThat(questionList.get(0).getAnswers().size()).isGreaterThan(0);
}
}
Iam using a hibernate entity class and have a ManyToOne relation with another model as follows
#ManyToOne
#JoinColumn(name ="`brand-id`", referencedColumnName="`id`", nullable=false, insertable = false, updatable = false)
private HotelBrand brand;
and my modal is as follows
#Entity
#Table(name = "`hotel`" })
public class Hotel implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="`id`", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Column(name="`brand-id`", nullable=false)
private Integer brandid;
#NotEmpty
#Column(name="`hotel-code`", nullable=false)
private String hotelid;
#NotEmpty
#Column(name="`hotel-name`", nullable=false)
private String hotelname;
#NotEmpty
#Column(name="`have-reports`", nullable=false)
private String havereports;
#ManyToOne
#JoinColumn(name ="`brand-id`", referencedColumnName="`id`", nullable=false, insertable = false, updatable = false)
private HotelBrand brand;
public Hotel() {}
public Hotel(Integer id, Integer brandid, String hotelid, String hotelname, HotelBrand brand ) {
super();
this.id = id;
this.brandid = brandid;
this.hotelid = hotelid;
this.hotelname = hotelname;
this.brand = brand;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getBrandid() {
return brandid;
}
public void setBrandid(Integer brandid) {
this.brandid = brandid;
}
public String getHotelid() {
return hotelid;
}
public void setHotelid(String hotelid) {
this.hotelid = hotelid;
}
public HotelBrand getBrand() {
return brand;
}
public void setBrand(HotelBrand brand) {
this.brand = brand;
}
public String getHotelname() {
return hotelname;
}
public void setHotelname(String hotelname) {
this.hotelname = hotelname;
}
}
so when fetching data iam getting joined column as seperate json object but i need only single column from that joined model.
Iam getting result as follows
{
"id": 115,
"brandid": 7,
"hotelid": "ABC",
"hotelname": "sample1",
"brand": {
"id": 7,
"brandname": "brand1"
}
}
But iam expecting as
{
"id": 115,
"brandid": 7,
"hotelid": "ABC",
"hotelname": "sample1",
"brandname": "brand1"
}
any help would be much appreciated.
You have to annotate the field brand with the annotation #JsonIgnore.
Than you will not received it in the json response
I would like to sovle this problec, cause it's looks interesting, to get grouped objects directly from box
I have db sheme about this:
Teacher
-id
-name
Group
-id
-name
Subject
-id
-name
Several teachers can teaches one subject
Subject_teachers
-subject_id
-teacher_id
Group_subjects
-group_id
-subject_id
I would to get grouped lessons by groups for teacher
class Teacher{
#Id id ,
...
#ManyToMany
???
Map<Group,Subject) subjects;
};
#Entity
#Table(name = "Teacher")
public class Teacher {
private Integer teacherId;
private String name;
private Set<SubjectTeachers> subjectTeachers = new HashSet<SubjectTeachers>(0);
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "teacher_id", unique = true, nullable = false)
public Integer getTeacherId() {
return teacherId;
}
public void setTeacherId(Integer teacherId) {
this.teacherId = teacherId;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setTitle(String name) {
this.name = name;
}
#OneToMany(mappedBy = "subjectTeachers", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Set<SubjectTeachers> getSubjectTeachers() {
return subjectTeachers;
}
public void setProjectTags(Set<SubjectTeachers> subjectTeachers) {
this.subjectTeachers = subjectTeachers;
}
}
#Entity
#Table(name = "Subject")
public class Subject{
private Integer subjectId;
private String name;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "subject_id", unique = true, nullable = false)
public Integer getSubjectId() {
return subjectId;
}
public void setSubjectId(Integer subjectId) {
this.subjectId = subjectId;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setTitle(String name) {
this.name = name;
}
}
#Entity
#Table(name ="subject_teachers")
public SubjectTeachers{
private Integer subjectTeachersID;
private Teacher teacher;
private Subject subject;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "subjectTeachersID", unique = true, nullable = false)
public Integer getSubjectTeachersId() {
return subjectTeachersID;
}
public void setSubjectTeachersId(Integer subjectTeachersID) {
this.subjectTeachersID = subjectTeachersID;
}
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "teacher_id", nullable = false)
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "subject_id", nullable = false)
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
#Entity
#Table(name = "group_subjects")
public class GroupSubjects{
private Integer groupId;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id", unique = true, nullable = false)
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
private Subject subject;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "subject_id", nullable = false)
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
Hope its help to you..
I followed this tutorial to implement in my domain model a many-to-many relationship with an extra column. It works great but I'm unable to create a criteria to query a field within the left side of my relation.
Taking this code
#Entity
#Table( name = "projects")
public class Project implements Cloneable, Serializable{
private Long id;
private String name;
private Set<ProjectOrganization> projectOrganizations = new HashSet<ProjectOrganization>(0);
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name", length = 255, nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.project")
#Cascade(value = { CascadeType.ALL })
public Set<ProjectOrganization> getProjectOrganizations() {
return this.projectOrganizations;
}
public void setProjectOrganizations(Set<ProjectOrganization> organizationProjects) {
this.projectOrganizations = organizationProjects;
}
}
#Entity
#Table(name = "projects_has_organizations")
#AssociationOverrides({ #AssociationOverride(name = "pk.project", joinColumns = #JoinColumn(name = "projects_id")),
#AssociationOverride(name = "pk.organization", joinColumns = #JoinColumn(name = "organizations_id"))
})
public class ProjectOrganization implements Cloneable, Serializable {
private ProjectOrganizationPK pk = new ProjectOrganizationPK();
private OrganizationRolesEnum role;
public ProjectOrganization() {
}
#Transient
public Organization getOrganization() {
return getPk().getOrganization();
}
public void setOrganization(Organization organization) {
getPk().setOrganization(organization);
}
#EmbeddedId
public ProjectOrganizationPK getPk() {
return pk;
}
public void setPk(ProjectOrganizationPK pk) {
this.pk = pk;
}
#Transient
public Project getProject() {
return getPk().getProject();
}
public void setProject(Project project) {
getPk().setProject(project);
}
#Enumerated(EnumType.STRING)
#Column(nullable = false, length = 50)
public OrganizationRolesEnum getRole() {
return role;
}
public void setRole(OrganizationRolesEnum role) {
this.role = role;
}
}
#Embeddable
public class ProjectOrganizationPK implements Cloneable, Serializable {
/** Generated serial version UID */
private static final long serialVersionUID = -4534322563105003365L;
private Organization organization;
private Project project;
#ManyToOne
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
#ManyToOne
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
#Entity
#Table(name = "organizations")
public class Organization implements Cloneable, Serializable {
private Long id;
private String name;
private Set<ProjectOrganization> projectOrganizations = new HashSet<ProjectOrganization>(0);
public Organization() {
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
#Override
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name", nullable = false, length = 255)
#NotNull(message = "A name is required!")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.organization")
public Set<ProjectOrganization> getProjectOrganization() {
return this.projectOrganizations;
}
public void setProjectOrganization(Set<ProjectOrganization> projectOrganizations) {
this.projectOrganizations = projectOrganizations;
}
}
I want is to create a criteria to select a Project which has an organization with a requested name.
final Criteria crit = getSession().createCriteria(Project.class);
crit.createCriteria("projectOrganizations", "projectOrganization").
createAlias("pk.organization", "organization").
add( Restrictions.like("organization.name", "TEST"));
But when i run this code i have this error
2012-10-19 10:38:43,095 ERROR [org.hibernate.util.JDBCExceptionReporter] Unknown column 'organizati2_.name' in 'where clause'
and the sql query generated by hibernate is incomplete, doesn't join projects_has_organizations.organization with organization.id.. So it can't find column organization.name
SELECT
....
FROM
projects this_
INNER JOIN projects_has_organizations projectorg1_ ON this_.id = projectorg1_.projects_id
WHERE
projectorg1_.role =?
AND organizati2_. NAME LIKE ?
ORDER BY
this_.publish_date DESC
What's wrong with this code? How can i build query using criteria ?
I suspect that the problem is due to lazy fetching, try explicitly telling hibernate to eagerly fetch the property you need. This is done with the method
.setFetchMode("propertyName", FetchMode.EAGER)
So, in otherwords, try eagerly fetch the organisation property :)