JPA onetomany mapping showing nested data many times - spring-boot

I have two table user(id,name) and user_mails(id,email,user_id) user to user_mails have one to many relation.
I have created following entity in spring boot
User
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "name", nullable = false)
private String name;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<UserMail> userMails =new HashSet<UserMail>(0);
//Getter setter and constructor
}
UserMail
#Entity
#Table(name = "user_mails")
public class UserMail {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name = "email", nullable = false)
private String name;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id")
private User user;
It is showing following output on calling controller
[{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":[{"id":2,"name":"ram#b.com","user":{"id":1,"name":"Ram","userMails":
and more
I want to access all users with all mail ids also want to acces mail id with user details
What changes should I do to get proper result

Related

Save entity with realtion

I have two entities with one-to-mane relationship:
#Entity
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
#JsonManagedReference
private List<RealEstate> realEstates = new ArrayList<>();
#Entity
public class RealEstate implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String name;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
#JsonBackReference
private User user;
I try to save realEstate entity with this code:
realEstate.setUser(user);
realEstateService.saveRealEstate(realEstate);
And this response:
[
{
"id": 1,
"name" : "Bueno",
"user" : 1
}
]
By all I have is creating new record in user table and relation with this new ID.
What I do wrong? What I need to read about this?
You first need to save User entity record and then RealEstate entity record.
Please read this article to implement One To Many relationship. I am sure your issue will be resolved.
https://attacomsian.com/blog/spring-data-jpa-one-to-many-mapping

#ManyToOne and #OneToMany ends up in unlimited loop when retrieved through profileRepository.getByProfileId(id);

Class Jobs has Many to One relationship with Profile.
When I retrieve through profileRepository.getByProfileId(id) the response returns recursive data.
Also if you notice Profile has Login object. I don't want to return that as well.
#Entity
#Table(name = "tbl_profile")
#Builder(toBuilder = true)
#NoArgsConstructor
#AllArgsConstructor
#Getter
public class Profile {
#Id
#Column(name = "profile_id")
#GeneratedValue(strategy = GenerationType.AUTO)
long profileId;
#NonNull
#Column(name = "name")
String name;
#Column(name = "description", nullable = false)
String description;
#OneToOne
#JoinColumn(name = "login_id",
referencedColumnName = "login_id")
Login login;
#OneToMany(
mappedBy = "profile"
)
List<Jobs> job;
Class Jobs
#Entity
#Table(name = "tbl_job")
#Builder(toBuilder = true)
#NoArgsConstructor
#AllArgsConstructor
#Getter
public class Jobs {
#Id
#Column(name = "job_id")
#GeneratedValue(strategy = GenerationType.AUTO)
long jobId;
#NonNull
#Column(name = "job_role", nullable = false)
String joRole;
#Column(name = "description", nullable = false)
String description;
#ManyToOne
#JoinColumn(name = "profile_id",
referencedColumnName = "profile_id")
Profile profile;
}
Use #JsonIgnore to the property to ignore the output on JSON. Also according to your business logic, recheck if you need bidirectional association. You could maybe add only unidirectional association.

#ManyToMany collection not populating with spring-boot-starter-data-jpa

I'm getting a problem with the #ManyToMany collections not populating on data load. I've tried FetchType.LAZY and FetchType.EAGER with no changes in the result.
When I am printing the User Object the collection Object of Roles is empty.
User [userId=2, firstName=Ajay, lastName=C, email=admin.demo#gmail.com, password=12345, roles=[]]
Also tried by adding referenced columns. But not worked.
Please assist in this.
User and Roles Entities as follows.
#Entity
#Table(name = "\"ROLE\"",schema="\"PLATFORM_PROD_IOT\"")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="\"ROLE_ID\"")
private Long roleId;
#Column(name="\"ROLE_NAME\"")
private RoleName name;
//Getters and Setters
}
#Entity
#Table(name = "\"USER\"", schema = "\"PLATFORM_PROD_IOT\"", uniqueConstraints = {
#UniqueConstraint(columnNames = { "\"EMAIL_ID\"" }) })
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Size(min = 1, max = 50)
#Column(name = "\"USER_ID\"")
private Long userId;
#NotBlank
#Size(min = 3, max = 50)
#Column(name = "\"FIRST_NAME\"")
private String firstName;
#NotBlank
#Size(min = 3, max = 50)
#Column(name = "\"LAST_NAME\"")
private String lastName;
#NaturalId
#NotBlank
#Size(max = 50)
#Email
#Column(name = "\"EMAIL_ID\"")
private String email;
#NotBlank
#Size(min = 3, max = 100)
#Column(name = "\"PASSWORD\"")
private String password;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "\"USER_ROLE_MAPPING\"", schema = "\"\PLATFORM_PROD_IOT\"", joinColumns = #JoinColumn(name = "\"USER_ID\""), inverseJoinColumns = #JoinColumn(name = "\"ROLE_ID\""))
private Set<Role> roles = new HashSet<>();
//Getters and Setters
}
#Entity
#Table(name = "\"ROLE\"",schema="\"PLATFORM_PROD_IOT\"")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="\"ROLE_ID\"")
private Long roleId;
#Column(name="\"ROLE_NAME\"")
private RoleName name;
//Getters and Setters
}
Try it in class Role.
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "USER_ROLE_MAPPING",joinColumns = #JoinColumn(name = "ROLE_ID"), inverseJoinColumns = #JoinColumn(name = "USER_ID""))
private Set<Role> roles = new HashSet<>();
And in class User change fetchType to EAGER. If it not work try change table to different name. Example: Users, Roles. Something it not work because it same name in SQL DATABASE.

Spring Framework + Spring Data + Hibernate Jpa OneToMany child removal fails

I have an unidirectional OneToMany JPA entity mapping in my (Spring Framework + Spring Data + Hibernate JPA) project. Entity classes are like in the following code.(I have removed irrelevant class members for brevity).
#Entity
#Table(name = "employees")
class Employee{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "employee_id")
private List<DepartmentAssignment> departmentAssignments = new ArrayList<>();
}
#Entity
#Table(name = "department_assignments")
class DepartmentAssignment{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#NotNull
#Column(name = "employee_id")
private Integer employeeId;
#NotNull
#Column(name = "department_id")
private Integer departmentId;
}
#Entity
#Table(name = "departments")
class Department{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
}
And, in one of my service classes have a method to remove a DepartmentAssignment from an Employee like below.
public Employee deleteDepartmentAssignment(Integer empId, Integer deptAssignmentId) {
Employee employee = employeeRepository.findOne(empId);
if(employee != null) {
for ( DepartmentAssignment da : employee.getDepartmentAssignments()) {
if(da.getId().equals(deptAssignmentId)) {
employee.getDepartmentAssignments().remove(da);
employee = employeeRepository.save(employee);
break;
}
}
}
return employee;
}
However, calling above methods gives me an error: org.hibernate.exception.ConstraintViolationException ,and in the SQL log, I can see Column 'employee_id' cannot be null error for the last SQL statement of the transaction.
Can anybody tell me what I'm doing wrong here and how to get it fixed?
You don't need to add
#NotNull
#Column(name = "employee_id")
private Integer employeeId;
to the Employee, if you use #JoinColumn(name = "employee_id"). Try to remove it.
You can try the following, not sure why you use the plain id in the object. Thats not object relational mapping.
For more details see Hibernate triggering constraint violations using orphanRemoval
#Entity
#Table(name = "employees")
class Employee{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "employee", orphanRemoval = true)
private List<DepartmentAssignment> departmentAssignments = new ArrayList<>();
}
#Entity
#Table(name = "department_assignments")
class DepartmentAssignment{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(optional=false)
private Employee employee;
#ManyToOne(optional=false)
private Department department;
}
#Entity
#Table(name = "departments")
class Department{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
}
You must look .hbm.xml file and you should mapping your Entity in this file and
you can look this example
http://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example/
I hope it will be useful for you.
try removing
cascade = CascadeType.ALL
but im not 100% sure..

one to many mapping in hibernate for a messaging service

I have two JPA entities: User and Message.
Each Message has one sender and one receiver of type User. And on the other side each User has two sets of type Message: inbox and outbox.
Message:
#Entity
#Table(name = "messages")
public class Message {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
#SequenceGenerator(name = "seq", sequenceName = "MESSAGES_SEQ")
#Column(name = "ID", insertable = false, updatable = false)
private int id;
#ManyToOne
#JoinColumn(name = "SENDER")
private User sender;
#ManyToOne
#JoinColumn(name = "RECEIVER")
private User receiver;
private String subject, content;
private Date sdate;
//getters and setters
}
All the properties which not being mapped with an annotation has he same name as the columns in database and are automatically mapped by JPA.
User:
#Entity
#Table(name = "users")
public class User {
#Column(name = "USERNAME")
private String username;
#Column(name = "PASSWORD")
private String pass;
#Column(name = "EMAIL")
private String email;
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
#SequenceGenerator(name = "seq", sequenceName = "USERS_SEQ")
#Column(name = "ID", insertable = false, updatable = false)
private int id;
#OneToMany(mappedBy = "uploader")
private Set<Book> books;
#OneToMany(mappedBy = "receiver")
private Set<Message> inbox;
#OneToMany(mappedBy = "sender")
private Set<Message> outbox;
//getters and setters
}
The problem is, when I select an User from Oracle database, then the inbox property is empty. How is this caused and how can I solve it?

Resources