Hibernate ManyToOne Repeating the relationship - java

I am using an Hibernate to manage the following relationship:
Dashboard.java:
#Entity
#Table(name = "dashboard")
public class Dashboard {
#Id
#Column(name = "dashboard_id", nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "type", nullable = false)
private String type;
#Column(name = "name", nullable = false)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToOne
#JoinColumn(name = "user_id", updatable = false)
private User user;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "dashwidgets")
public List<Widget> widgets;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
and Widget.java
#Entity
#Table(name = "Widget")
public class Widget {
#Id
#Column(name = "widget_id", nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "widgetlayout_id")
private WidgetLayout layout;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "dashboard_id")
public Dashboard dashwidgets;
public WidgetLayout getLayout() {
return layout;
}
public void setLayout(WidgetLayout layout) {
this.layout = layout;
}
#Column(name = "widget_type", nullable = false)
private String widgetType;
public Widget() {
}
public Widget(long id, String widgetType) {
this.id = id;
this.widgetType = widgetType;
}
#Column(name = "resizeable")
public boolean resizable;
#Column(name = "canpopout")
public boolean canpopout;
#Column(name = "settings", columnDefinition = "CLOB NOT NULL")
public String settings;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getWidgetType() {
return widgetType;
}
public void setWidgetType(String widgetType) {
this.widgetType = widgetType;
}
}
What I'm expecting is that a Dashboard can a list of Widgets. Each Widget belongs to One dashboard. However, the generated POJO looks like this:
{
"Id": 0,
"Type": "string",
"Name": "string",
"User": {
"Id": 0,
"Username": "string"
},
"Widgets": [
{
"Id": 0,
"Layout": {
"Id": 0,
"Col": 0,
"Row": 0,
"Sizex": 0,
"Sizey": 0
},
"Dashwidgets": {},
"WidgetType": "string",
"Resizable": false,
"Canpopout": false,
"Settings": "string"
}
]
}
For some reason It's adding "Widgets": as a proper POJO and then an additional "Dashwidgets": {}.
When I save the object, Only the DashWidgets object is saved.
What am I doing wrong?

Take off the mappedBy from widgets. When you add `mappedBy' is actually gives the control of saving object to Child Entity.
#OneToMany(cascade = CascadeType.ALL)
public List<Widget> widgets;
Check out this question for more information.

Related

Spring boot lazy loaded entity not loading all properties

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.

Hibernate #JoinColumn and fetch single column instead of model object

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

Hibernate many-to-one mapping set previous foreign keys as NULL

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.

Hibernate #Many to many grouped map mapping

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..

Hibernate mapping in Java: org.hibernate.MappingException: Repeated column in mapping for entity

I try to gather statistics of visitors for two services. It consists of daily visitors statistics and overall record. Each service can be accessed by different names. For example, user, admin, support etc. Each will have its own record as own statistics.
Here is my DB structure:
service_one: id, name
service_two: id, name
daily_stats: id, date, service_one_id, service_one_visitors,
service_two_id, service_two_visitors, overall_visitors
record_stats: id, service_one_id, service_one_record,
service_one_record_date, service_two_id, service_two_record,
service_two_record_date
Here are the relations between tables:
service_one --- (one to many) ---> daily_stats(service_one_id)
service_one --- (one to many) ---> record_stats(service_one_id)
service_two --- (one to many) ---> daily_stats(service_two_id)
service_two --- (one to many) ---> record_stats(service_two_id)
Mapping for service_one (the same is for service_two). Also setters were omitted in order to shorten the example:
#Entity
#Table(name = "service_one")
public class ServiceOne implements Serializable {
private int id;
private String name;
private Set<RecordStats> recordStats = new HashSet<RecordStats>(0);
private Set<DailyStats> dailyStats = new HashSet<DailyStats>(0);
public ServiceOne() {}
public ServiceOne(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", nullable = false, unique = true)
public int getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<RecordStats> getRecordStats() {
return recordStats;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<DailyStats> getDailyStats() {
return dailyStats;
}
}
daily_stats mapping:
#Entity
#Table(name = "daily_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "date")
})
public class DailyStats implements Serializable{
private int id;
private Date date;
private ServiceOne service_one_id;
private int service_one_visitors;
private ServiceTwo service_two_id;
private int service_two_visitors;
private int overall_visitors;
public DailyStats() {}
public DailyStats(DailyStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#Temporal(DATE)
#Column(name = "date")
public Date getDate() {
return date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_visitors")
public int getService_one_visitors() {
return service_one_visitors;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_visitors")
public int getService_two_visitors() {
return service_two_visitors;
}
#Column(name = "overall_visitors")
public int getOverall_visitors() {
return overall_visitors;
}
}
record_stats mapping:
#Entity
#Table(name = "record_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "service_one_record_date"),
#UniqueConstraint(columnNames = "service_two_record_date")
})
public class RecordStats implements Serializable {
private int id;
private ServiceOne service_one_id;
private int service_one_record;
private Date service_one_rec_date;
private ServiceTwo service_two_id;
private int service_two_record;
private Date service_two_rec_date;
public RecordStats() {}
public RecordStats(RecordStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_record")
public int getService_one_record() {
return service_one_record;
}
#Column(name = "service_one_record_date")
#Temporal(DATE)
public Date getService_one_rec_date() {
return service_one_rec_date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_record")
public int getService_two_record() {
return service_two_record;
}
#Column(name = "service_two_record_date")
#Temporal(DATE)
public Date getService_two_rec_date() {
return service_two_rec_date;
}
}
Trying to create new entry throws exception:
public static void main(String[] args) {
ServiceOne serviceOne = new ServiceOne();
serviceOne.setName("test");
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(serviceOne);
session.getTransaction().commit();
//get records
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery("from service_one").list();
for (ServiceOne o : (List<ServiceOne>)result) {
System.out.println(o.getName());
}
session.getTransaction().commit();
session.close();
}
org.hibernate.MappingException: Repeated column in mapping for entity:
VisitorsCounter.model.entity.DailyStats column: id (should be
mapped with insert="false" update="false")
What is wrong with my mapping?
It seems to me that
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
in DailyStats is wrong; you should have name = "service_one_id".
You have the same problem in getService_two_id() and in methods of same names in RecordStats.
May I also ask why don't you name the references in the classes fields serviceOne and serviceTwo instead of service_one_id and service_two_id.

Categories

Resources