OneToMany fetch lazy not working with spring boot + JPA - spring-data-jpa

I have two entities. Student and department.One department has many student. I have specified fetch type lazy. still when I am trying to fetch only department entity it is showing student data as well.
#Entity(name = "tbl_department")
public class DepartmentEntity implements Serializable {
private static final long serialVersionUID = 1560990434803170482L;
#Id
#GeneratedValue
private Integer id;
#NotNull(message = "Department name can not be null")
private String departmentName;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "department", fetch = FetchType.LAZY)
private Set<StudentEntity> studentList;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public Set<StudentEntity> getStudentList() {
return studentList;
}
public void setStudentList(Set<StudentEntity> studentList) {
this.studentList = studentList;
}
#Entity(name = "tbl_student")
public class StudentEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2969421115938100526L;
#Id
#GeneratedValue
private Integer id;
#NotNull(message = "First Name Can not null")
private String firstName;
#NotNull(message = "Last Name Can not null")
private String lastName;
#NotNull(message = "Date Of Birth Can not null")
private Date dateOfBirth;
private Integer age;
#NotNull(message = "Address Can not null")
private String address;
#JsonIgnore
#ManyToOne(cascade = CascadeType.ALL)
private DepartmentEntity department;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public DepartmentEntity getDepartment() {
return department;
}
public void setDepartment(DepartmentEntity department) {
this.department = department;
}
So when I am trying to fetch department entity using departmentRepo it shows all students mapped to that department even if I specified fetch type lazy

Can you declare your entities as below and try once
Student Entity:
#OrderBy("id ASC")
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="departmentid")
#JsonIgnore
private Department department;
Department Entity:
#OrderBy("id ASC")
#OneToMany(fetch=FetchType.LAZY, mappedBy="department")
private Set<Student> students = new LinkedHashSet<Student>(0);

Related

JPA mapping to a collection of objects of same class

I have an Entity which contains a collection of another Entity which itself references the same class in a collection, with the following mappings:
#Entity
#Table(name="parents")
public class Parent {
#Id
#GeneratedValue
private long id;
#ElementCollection
#Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Child> children;
public Parent() {}
public Parent(Set<Child> children) {
this.children = children;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
#Entity
#Table(name="children")
public static class Child {
#Id
#GeneratedValue
private long id;
private String name;
#ElementCollection
#Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Child> dependencies;
public Child() {}
public Child(String name) {
this.name = name;
dependencies = new LinkedHashSet<>();
}
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 getDependencies() {
return dependencies;
}
public setDependencies(Set<Child> dependencies) {
this.dependencies = dependencies;
}
}
}
But when I try to save it, I get a: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing exception
I've read in another post that I should use #Cascade(CascadeType.ALL) annotation, but as you can see, I tried doing so and it didn't solve my problem.
Please help me understand what's wrong with these mappings

Duplicate entry when trying to save Entity

I have an Entity which contains another Entity in a collection, which itself contains a collection of entities of the same class, like so:
#Entity
#Table(name="parents")
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#OneToMany(cascade = CascadeType.ALL)
private Set<Task> tasks;
public Parent() {}
public Parent(Set<Task> tasks) {
this.tasks = tasks;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Set<Task> getTasks() {
return tasks;
}
public void setTasks(Set<Task> tasks) {
this.tasks = tasks;
}
#Entity
#Table(name="tasks")
public static class Task {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "task_id")
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL)
private Set<Task> dependencies;
public Task() {}
public Task(String name) {
this.name = name;
dependencies = new LinkedHashSet<>();
}
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 Set<Task> getDependencies() {
return dependencies;
}
public void setDependencies(Set<Task> dependencies) {
this.dependencies = dependencies;
}
}
}
The problem in my case is that two Task may reference the same Task in their dependencies, and so when I try to save my Parent, I get a org.hibernate.exception.ConstraintViolationException: could not execute statement and SQL says: Duplicate entry '12' for key 'UK_q8xuxyx9iylvc9ddh8fudtlsf'
How can I overcome this issue ? Any help is appreciated.

JAVA Javax Embeded Entity with SpringBoot and Vaadin, cant make a Column

maybe someone can tell me why I cant inject Embeded Column to my Facility.class? I want to make a column from ContactPerson.class PrimaryKeys in Facility.class Table, after that I want to make contructor in Facility.class to add ContactPerson. I'm kind new to SpringBoot + Jpa and Vaadin ^^
Here is the error message I get, im sure I overlooking something:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: component property not found: id
Caused by: org.hibernate.MappingException: component property not found: id
at org.hibernate.mapping.Component.getProperty(Component.java:274) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
Facility.class
#Entity
public class Facility extends BaseEntity {
public Facility(#NotBlank String number, #NotBlank String name, #NotBlank String street, String extraInformation,
#NotBlank String zipcode, #NotBlank String city, **ContactPerson contactPerson**) {
this.number = number;
this.name = name;
this.street = street;
this.extraInformation = extraInformation;
this.zipcode = zipcode;
this.city = city;
**//this.contactPerson = contactPerson;**
}
#NotBlank
#Column(unique = true)
private String number;
#NotBlank
private String name;
#NotBlank
private String street;
private String extraInformation;
#NotBlank
private String zipcode;
#NotBlank
private String city;
#Embedded
#Column(columnDefinition = "contactperson")
private ContactPerson contactPerson;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getExtraInformation() {
return extraInformation;
}
public void setExtraInformation(String extraInformation) {
this.extraInformation = extraInformation;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public ContactPerson getContactPerson() {
return contactPerson;
}
public void setContactPerson(ContactPerson contactPerson) {
this.contactPerson = contactPerson;
}
}
ContactPerson.class
#Embeddable
public class ContactPerson extends BaseEntity {
public ContactPerson(#NotBlank String titel, #NotBlank String firstName, #NotBlank String lastName, String telefon, String mobil, #Email String email) {
this.titel = titel;
this.firstName = firstName;
this.lastName = lastName;
this.telefon = telefon;
this.mobil = mobil;
this.email = email;
}
#NotBlank
private String titel;
#NotBlank
private String firstName;
#NotBlank
private String lastName;
private String telefon;
private String mobil;
#Email
private String email;
public String getTitel() {
return titel;
}
public void setTitel(String titel) {
this.titel = titel;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getTelefon() {
return telefon;
}
public void setTelefon(String telefon) {
this.telefon = telefon;
}
public String getMobil() {
return mobil;
}
public void setMobil(String mobil) {
this.mobil = mobil;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
BaseEntity.class
public abstract class BaseEntity extends AbstractAggregateRoot<BaseEntity> {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
protected long getId() {
return this.id;
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || this.getClass() != o.getClass())
return false;
BaseEntity that = (BaseEntity) o;
return Objects.equals(this.id, that.id);
}
#Override
public int hashCode() {
return Objects.hash(this.id);
}
#Override
public String toString() {
return "BaseEntity{" +
"id=" + this.id +
'}';
}
}
After long try I found out where was the problem. The ContactPerson.class after Embeding is not a Entity anymore so it doesnt need the extensions of BaseEntity.class but it will need the default constructor to start. Annotation #Embedded not needed in Java9
ContactPerson.class
#Embeddable
public class ContactPerson {
public ContactPerson(#NotBlank String titel, #NotBlank String firstName, #NotBlank String lastName, String telefon, String mobil, #Email String email) {
this.titel = titel;
this.firstName = firstName;
this.lastName = lastName;
this.telefon = telefon;
this.mobil = mobil;
this.email = email;
}
public ContactPerson() {
}
#NotBlank
private String titel;
#NotBlank
private String firstName;
#NotBlank
private String lastName;
private String telefon;
private String mobil;
#Email
private String email;
public String getTitel() {
return titel;
}
public void setTitel(String titel) {
this.titel = titel;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getTelefon() {
return telefon;
}
public void setTelefon(String telefon) {
this.telefon = telefon;
}
public String getMobil() {
return mobil;
}
public void setMobil(String mobil) {
this.mobil = mobil;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Facility.class
#Entity
public class Facility extends BaseEntity {
public Facility(#NotBlank String number, #NotBlank String name, #NotBlank String street, String extraInformation, #NotBlank String zipcode, #NotBlank String city, ContactPerson contactPerson) {
this.number = number;
this.name = name;
this.street = street;
this.extraInformation = extraInformation;
this.zipcode = zipcode;
this.city = city;
this.contactPerson = contactPerson;
}
public Facility() {
}
#NotBlank
#Column(unique = true)
private String number;
#NotBlank
private String name;
#NotBlank
private String street;
private String extraInformation;
#NotBlank
private String zipcode;
#NotBlank
private String city;
private ContactPerson contactPerson;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getExtraInformation() {
return extraInformation;
}
public void setExtraInformation(String extraInformation) {
this.extraInformation = extraInformation;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public ContactPerson getContactPerson() {
return contactPerson;
}
public void setContactPerson(ContactPerson contactPerson) {
this.contactPerson = contactPerson;
}
}

How to store id as string in mongo db

I am new to mongo DB. I have three attributes in my object as below:
{
"id":"id"
"name":"Name field",
"description":"Description field"
}
If I pass Id as string from spring boot application. Then it's getting stored as object. Is it possible to store id as what customer wants?
Below is my object class:
#Document
public class Topic {
#Id
private String id;
private String name;
private String description;
public Topic() {
}
public Topic(String id, String name, String description) {
this.id= id;
this.name = name;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

JPA - Repeated column in mapping for entity #OneToOne

I have two simple tables: Users and User_Roles.
In both tables i have a field email and i want load User_Roles from UserEntity, the query should be:
SELECT *
FROM Users u, User_Roles ur
WHERE u.email = ur.email;
When i try to "link" the email field i get the error "Repeated column in mapping for entity: UserEntity column: email".
I've tried to add any kind of combination (mappedBy, refColumn etc) but the error is even the same...
User
#Entity
#Table(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String email;
private UserRolesEntity roles;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#OneToOne
#JoinColumn(name = "email")
public UserRolesEntity getRoles() {
return roles;
}
public void setRoles(UserRolesEntity roles) {
this.roles = roles;
}
}
User_Roles
#Entity
#Table(name = "user_roles")
public class UserRolesEntity {
private long id;
private String email;
private String role;
#Id
#Column(name = "user_role_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Basic
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
If you want to link the User_Roles and User, you should keep the User's primary key in User_Roles. So you would better modify your User_Roles table like this:
long user_role_id
long user
String role
Then your User_Roles class would be:
#Entity
#Table(name = "user_roles")
public class UserRolesEntity {
private long id;
private User user;
private String role;
#Id
#Column(name = "user_role_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#OneToOne
public User getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
#Basic
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
If you want get the user email from user_role, you can do like this: userRole.getUser().getEmail()
And then the User class would be:
#Entity
#Table(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String email;
private UserRolesEntity roles;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Basic
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#OneToOne(mappedBy="user")
public UserRolesEntity getRoles() {
return roles;
}
public void setRoles(UserRolesEntity roles) {
this.roles = roles;
}
}