Dynamic type caste Spring pathvariable - spring

I am planning to create one simple Spring Rest Service Project with JPA which will fetch the details from the database based on the entity name and entity id given in path variables.
consider following code.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ds.dao.EntityDAO;
import com.ds.entities.Employees;
import javax.persistence.Entity;
#Controller
#RequestMapping("/")
public class DynaRestController {
#Autowired
EntityDAO entityDAO;
#RequestMapping(value = "{entityName}/{enityId}",method = RequestMethod.GET)
public #ResponseBody Object getEntity(#PathVariable("entityName") String entityName,#PathVariable("enityId") Object id) {
return entityDAO.getEntityById(entityName, id);
}
}
Entity DAO Class
public class EntityDAO {
#Autowired
EntityManager entityManager;
public Object getEntityById(String entityName, Object id) {
EntityType<?> entityType = getEntityByName(entityName);
Object idcasted = entityType.getIdType().getJavaType().cast(id);
System.out.println(idcasted.getClass().getName());
Object entity = entityManager.find(entityType.getJavaType(), idcasted);
System.out.println("Entity.. Name .." + entityName);
// Employees entity = session.load(Employees.class, id);
return entity;
}
private EntityType<?> getEntityByName(String name) {
Set<EntityType<?>> entities = entityManager.getMetamodel().getEntities();
for (Iterator<EntityType<?>> iterator = entities.iterator(); iterator.hasNext();) {
EntityType<?> entityType = (EntityType<?>) iterator.next();
if (entityType.getName().equals(name))
return entityType;
}
return null;
}
}
Employees Class
#Configurable
#Entity
#Table(name = "employees", catalog = "employees")
public class Employees implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int empNo;
private Date birthDate;
private String firstName;
private String lastName;
private String gender;
private Date hireDate;
private Set<Titles> titleses = new HashSet<Titles>(0);
private Set<Salaries> salarieses = new HashSet<Salaries>(0);
private Set<DeptEmp> deptEmps = new HashSet<DeptEmp>(0);
private Set<DeptManager> deptManagers = new HashSet<DeptManager>(0);
public Employees() {
}
public Employees(int empNo, Date birthDate, String firstName, String lastName, String gender, Date hireDate) {
this.empNo = empNo;
this.birthDate = birthDate;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.hireDate = hireDate;
}
public Employees(int empNo, Date birthDate, String firstName, String lastName, String gender, Date hireDate,
Set<Titles> titleses, Set<Salaries> salarieses, Set<DeptEmp> deptEmps, Set<DeptManager> deptManagers) {
this.empNo = empNo;
this.birthDate = birthDate;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.hireDate = hireDate;
this.titleses = titleses;
this.salarieses = salarieses;
this.deptEmps = deptEmps;
this.deptManagers = deptManagers;
}
#Id
#Column(name = "emp_no", unique = true, nullable = false)
public int getEmpNo() {
return this.empNo;
}
public void setEmpNo(int empNo) {
this.empNo = empNo;
}
#Temporal(TemporalType.DATE)
#Column(name = "birth_date", nullable = false, length = 10)
public Date getBirthDate() {
return this.birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
#Column(name = "first_name", nullable = false, length = 14)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "last_name", nullable = false, length = 16)
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name = "gender", nullable = false, length = 2)
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
#Temporal(TemporalType.DATE)
#Column(name = "hire_date", nullable = false, length = 10)
public Date getHireDate() {
return this.hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
public Set<Titles> getTitleses() {
return this.titleses;
}
public void setTitleses(Set<Titles> titleses) {
this.titleses = titleses;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
public Set<Salaries> getSalarieses() {
return this.salarieses;
}
public void setSalarieses(Set<Salaries> salarieses) {
this.salarieses = salarieses;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
#JsonBackReference
public Set<DeptEmp> getDeptEmps() {
return this.deptEmps;
}
public void setDeptEmps(Set<DeptEmp> deptEmps) {
this.deptEmps = deptEmps;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "employees")
public Set<DeptManager> getDeptManagers() {
return this.deptManagers;
}
public void setDeptManagers(Set<DeptManager> deptManagers) {
this.deptManagers = deptManagers;
}
}
When i am dynamically casting the path variable by using following code
Object idcasted = entityType.getIdType().getJavaType().cast(id);
Object entity = entityManager.find(entityType.getJavaType(), idcasted);
it is throwing ClassCastExpcetion
java.lang.ClassCastException: Cannot cast java.lang.String to int
at java.lang.Class.cast(Class.java:3369) ~[na:1.8.0_112]
at com.techm.att.ds.dao.EntityDAO.getEntityById(EntityDAO.java:33) ~[classes/:na]
at com.techm.att.ds.dao.EntityDAO$$FastClassBySpringCGLIB$$8e64d745.invoke() ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
any Help will be highly appriciated..

I write you a simple example regarding the comments.
This is the same behavior. Your RestController gets actually a string:
public static void main(String[] args) {
Object myString = "myString";
System.out.println(myString.getClass()); // class java.lang.String
int.class.cast(myString);
}
The cast method checks the instanceof your given value and it fails:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}

Related

The primary key of the parent table is the primary key of the child table, How can I map it using jpa?

This is the diagram:
References: https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html
I get the list from the batch_job_execution_params table but the data is repeated with the information in the first row, the count is correct.
My Entity classes are as follows:
BATCH_JOB_EXECUTION TABLE
package com.maxcom.interfact_services.entity;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
#Entity
#Table(name = "BATCH_JOB_EXECUTION")
public class BatchJobExecutionEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "JOB_EXECUTION_ID", nullable = false)
private Long jobExecutionId;
#Column(name = "VERSION")
private Long version;
#ManyToOne
#JoinColumn(name = "JOB_INSTANCE_ID", nullable = false, updatable = false)
private BatchJobInstanceEntity jobInstanceId;
#Column(name = "CREATE_TIME")
#Temporal(TemporalType.TIMESTAMP)
private Date createTime;
#Column(name = "START_TIME")
#Temporal(TemporalType.TIMESTAMP)
private Date startTime;
#Column(name = "END_TIME")
#Temporal(TemporalType.TIMESTAMP)
private Date endTime;
#Column(name = "STATUS")
private String status;
#Column(name = "EXIT_CODE")
private String exitCode;
#Column(name = "EXIT_MESSAGE")
private String exitMessage;
#Column(name = "LAST_UPDATED")
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdated;
#Column(name = "JOB_CONFIGURATION_LOCATION")
private String jobConfigurationLocation;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "batchJobExecutionEntity", orphanRemoval = true)
private Set<BatchStepExecutionEntity> batchSteps;
#JsonManagedReference
#MapsId("jobExecutionId")
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "jobExecutionId", orphanRemoval = true)
// #JsonIgnoreProperties("batchJobExecutionEntity")
private List<BatchJobExecutionParamsEntity> batchJobParams = new ArrayList<>();
public BatchJobExecutionEntity() {
}
public Long getJobExecutionId() {
return jobExecutionId;
}
public void setJobExecutionId(Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
#JsonBackReference
public BatchJobInstanceEntity getJobInstanceId() {
return jobInstanceId;
}
public void setJobInstanceId(BatchJobInstanceEntity jobInstanceId) {
this.jobInstanceId = jobInstanceId;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getExitCode() {
return exitCode;
}
public void setExitCode(String exitCode) {
this.exitCode = exitCode;
}
public String getExitMessage() {
return exitMessage;
}
public void setExitMessage(String exitMessage) {
this.exitMessage = exitMessage;
}
public Date getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getJobConfigurationLocation() {
return jobConfigurationLocation;
}
public void setJobConfigurationLocation(String jobConfigurationLocation) {
this.jobConfigurationLocation = jobConfigurationLocation;
}
#JsonManagedReference
public Set<BatchStepExecutionEntity> getBatchSteps() {
return batchSteps;
}
public void setBatchSteps(Set<BatchStepExecutionEntity> batchSteps) {
this.batchSteps = batchSteps;
}
public List<BatchJobExecutionParamsEntity> getBatchJobParams() {
return batchJobParams;
}
public void setBatchJobParams(List<BatchJobExecutionParamsEntity> batchJobParams) {
this.batchJobParams = batchJobParams;
}
}
BATCH_JOB_EXECUTION_PARAMS TABLE
package com.maxcom.interfact_services.entity;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
#Entity
#Table(name = "BATCH_JOB_EXECUTION_PARAMS")
public class BatchJobExecutionParamsEntity implements Serializable {
#Id
// #GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "JOB_EXECUTION_ID", length = 20)
private Long jobExecutionId;
// #JsonBackReference
// #ManyToOne(fetch = FetchType.LAZY)
// #JoinColumn(name= "JOB_EXECUTION_ID", insertable = false, updatable = false)
// #JsonIgnoreProperties("batchJobParams")
// private BatchJobExecutionEntity batchJobExecutionEntity;
#Column(name = "TYPE_CD", length = 6)
private String typeCd;
#Column(name = "KEY_NAME", length = 100)
private String keyName;
#Column(name = "STRING_VAL", length = 250)
private String stringVal;
#Column(name = "DATE_VAL")
#Temporal(TemporalType.TIMESTAMP)
private Date dateVal;
#Column(name = "LONG_VAL")
private Long longVal;
#Column(name = "DOUBLE_VAL")
private Double doubleVal;
#Column(name = "IDENTIFYING", columnDefinition = "char(1)")
private String identifying;
public BatchJobExecutionParamsEntity() {
}
public Long getJobExecutionId() {
return jobExecutionId;
}
public void setJobExecutionId(Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
public String getTypeCd() {
return typeCd;
}
public void setTypeCd(String typeCd) {
this.typeCd = typeCd;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
public String getStringVal() {
return stringVal;
}
public void setStringVal(String stringVal) {
this.stringVal = stringVal;
}
public Date getDateVal() {
return dateVal;
}
public void setDateVal(Date dateVal) {
this.dateVal = dateVal;
}
public Long getLongVal() {
return longVal;
}
public void setLongVal(Long longVal) {
this.longVal = longVal;
}
public Double getDoubleVal() {
return doubleVal;
}
public void setDoubleVal(Double doubleVal) {
this.doubleVal = doubleVal;
}
public String getIdentifying() {
return identifying;
}
public void setIdentifying(String identifying) {
this.identifying = identifying;
}
/*
public BatchJobExecutionEntity getBatchJobExecutionEntity() {
return batchJobExecutionEntity;
}
public void setBatchJobExecutionEntity(BatchJobExecutionEntity batchJobExecutionEntity) {
this.batchJobExecutionEntity = batchJobExecutionEntity;
}
*/
}
How to map 1:N of this scenario?
Having a non-unique primary key is a recipe for disaster (/duplicates).
You missed Appendix B.3:
Note that there is no primary key for this table. This is because the framework has no use for one and, thus, does not require it. If need be, you can add a primary key may be added with a database generated key without causing any issues to the framework itself.
So you can either add a generated primary key to the table and use it as Id or create an EmbeddedId / IdClass on BatchJobExecutionParamsEntity with all the fields.
my solution was the following based on the answer from #Lookslikeitsnot and also to the following article: https://fullstackdeveloper.guru/2021/08/25/what-is-mapsid-used-for-in-jpa-hibernate-part-ii/
The keywords in this scenario were:
#Embeddable
#EmbeddedId
#MapsId
I Share my final code:
- BatchJobExecutionParamsEntity: (Child Table)
package com.maxcom.interfact_services.entity;
import com.fasterxml.jackson.annotation.JsonBackReference;
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table(name = "BATCH_JOB_EXECUTION_PARAMS")
public class BatchJobExecutionParamsEntity implements Serializable {
#EmbeddedId
private BatchJobParamIdEmbedded id;
#JsonBackReference
#ManyToOne
#MapsId("jobExecutionId")
#JoinColumn(name= "JOB_EXECUTION_ID", insertable = false, updatable = false)
private BatchJobExecutionEntity batchJobExecutionEntity;
public BatchJobExecutionParamsEntity() {
}
public BatchJobParamIdEmbedded getId() {
return id;
}
public void setId(BatchJobParamIdEmbedded id) {
this.id = id;
}
public BatchJobExecutionEntity getBatchJobExecutionEntity() {
return batchJobExecutionEntity;
}
public void setBatchJobExecutionEntity(BatchJobExecutionEntity batchJobExecutionEntity) {
this.batchJobExecutionEntity = batchJobExecutionEntity;
}
}
- BatchJobParamIdEmbedded: (Embedded Entity)
package com.maxcom.interfact_services.entity;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.io.Serializable;
import java.util.Date;
#Embeddable
public class BatchJobParamIdEmbedded implements Serializable {
private Long jobExecutionId; // composite key class
#Column(name = "TYPE_CD", length = 6)
private String typeCd;
#Column(name = "KEY_NAME", length = 100)
private String keyName;
#Column(name = "STRING_VAL", length = 250)
private String stringVal;
#Column(name = "DATE_VAL")
#Temporal(TemporalType.TIMESTAMP)
private Date dateVal;
#Column(name = "LONG_VAL")
private Long longVal;
#Column(name = "DOUBLE_VAL")
private Double doubleVal;
#Column(name = "IDENTIFYING", columnDefinition = "char(1)")
private String identifying;
public Long getJobExecutionId() {
return jobExecutionId;
}
public void setJobExecutionId(Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
public String getTypeCd() {
return typeCd;
}
public void setTypeCd(String typeCd) {
this.typeCd = typeCd;
}
public String getKeyName() {
return keyName;
}
public void setKeyName(String keyName) {
this.keyName = keyName;
}
public String getStringVal() {
return stringVal;
}
public void setStringVal(String stringVal) {
this.stringVal = stringVal;
}
public Date getDateVal() {
return dateVal;
}
public void setDateVal(Date dateVal) {
this.dateVal = dateVal;
}
public Long getLongVal() {
return longVal;
}
public void setLongVal(Long longVal) {
this.longVal = longVal;
}
public Double getDoubleVal() {
return doubleVal;
}
public void setDoubleVal(Double doubleVal) {
this.doubleVal = doubleVal;
}
public String getIdentifying() {
return identifying;
}
public void setIdentifying(String identifying) {
this.identifying = identifying;
}
}
- BatchJobExecutionEntity: (Parent Table)
package com.maxcom.interfact_services.entity;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#Entity
#Table(name = "BATCH_JOB_EXECUTION")
public class BatchJobExecutionEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "JOB_EXECUTION_ID", nullable = false)
private Long jobExecutionId;
#Column(name = "VERSION")
private Long version;
#ManyToOne
#JoinColumn(name = "JOB_INSTANCE_ID", nullable = false, updatable = false)
private BatchJobInstanceEntity jobInstanceId;
#Column(name = "CREATE_TIME")
#Temporal(TemporalType.TIMESTAMP)
private Date createTime;
#Column(name = "START_TIME")
#Temporal(TemporalType.TIMESTAMP)
private Date startTime;
#Column(name = "END_TIME")
#Temporal(TemporalType.TIMESTAMP)
private Date endTime;
#Column(name = "STATUS")
private String status;
#Column(name = "EXIT_CODE")
private String exitCode;
#Column(name = "EXIT_MESSAGE")
private String exitMessage;
#Column(name = "LAST_UPDATED")
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdated;
#Column(name = "JOB_CONFIGURATION_LOCATION")
private String jobConfigurationLocation;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "batchJobExecutionEntity", orphanRemoval = true)
private List<BatchStepExecutionEntity> batchSteps;
#JsonManagedReference
#OneToMany(mappedBy = "batchJobExecutionEntity", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private List<BatchJobExecutionParamsEntity> batchJobParams = new ArrayList<>();
public BatchJobExecutionEntity() {
}
public Long getJobExecutionId() {
return jobExecutionId;
}
public void setJobExecutionId(Long jobExecutionId) {
this.jobExecutionId = jobExecutionId;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
#JsonBackReference
public BatchJobInstanceEntity getJobInstanceId() {
return jobInstanceId;
}
public void setJobInstanceId(BatchJobInstanceEntity jobInstanceId) {
this.jobInstanceId = jobInstanceId;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getExitCode() {
return exitCode;
}
public void setExitCode(String exitCode) {
this.exitCode = exitCode;
}
public String getExitMessage() {
return exitMessage;
}
public void setExitMessage(String exitMessage) {
this.exitMessage = exitMessage;
}
public Date getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public String getJobConfigurationLocation() {
return jobConfigurationLocation;
}
public void setJobConfigurationLocation(String jobConfigurationLocation) {
this.jobConfigurationLocation = jobConfigurationLocation;
}
#JsonManagedReference
public List<BatchStepExecutionEntity> getBatchSteps() {
return batchSteps;
}
public void setBatchSteps(List<BatchStepExecutionEntity> batchSteps) {
this.batchSteps = batchSteps;
}
public List<BatchJobExecutionParamsEntity> getBatchJobParams() {
return batchJobParams;
}
public void setBatchJobParams(List<BatchJobExecutionParamsEntity> batchJobParams) {
this.batchJobParams = batchJobParams;
}
/* Add an batchJobParam to jobExecution Entity to maintain the bi-directional OneToMapping */
public void addBatchJobExecutionParam(BatchJobExecutionParamsEntity batchJobParam) {
this.batchJobParams.add(batchJobParam);
batchJobParam.setBatchJobExecutionEntity(this);
}
}
As shown in the following image, I now get different objects, of course encapsulated in the id (BatchJobParamIdEmbedded):
The second picture shows more details:
Thank you all for your support.
Best regards

Error mapping OneToMany or ManyToOne unmapped class

I have this problem :
Error creating bean with name 'ICustomerDao' defined in com.biblio.fr.biblio.repository.ICustomerDao defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.biblio.fr.biblio.entite.Book.loans[com.biblio.fr.biblio.entite.Loan]
this is my code :
#Entity
#Table(name = "BOOK")
public class Book {
private Integer id;
private String title;
private String isbn;
private LocalDate releaseDate;
private LocalDate registerDate;
private Integer totalExamplaries;
private String author;
private Category category;
Set<Loan> loans = new HashSet<Loan>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "BOOK_ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "TITLE", nullable = false)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "ISBN", nullable = false, unique = true)
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
#Column(name = "RELEASE_DATE", nullable = false)
public LocalDate getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(LocalDate releaseDate) {
this.releaseDate = releaseDate;
}
#Column(name = "REGISTER_DATE", nullable = false)
public LocalDate getRegisterDate() {
return registerDate;
}
public void setRegisterDate(LocalDate registerDate) {
this.registerDate = registerDate;
}
#Column(name = "TOTAL_EXAMPLARIES")
public Integer getTotalExamplaries() {
return totalExamplaries;
}
public void setTotalExamplaries(Integer totalExamplaries) {
this.totalExamplaries = totalExamplaries;
}
#Column(name = "AUTHOR")
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
#ManyToOne(optional = false)
#JoinColumn(name = "CAT_CODE", referencedColumnName = "CODE")
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
// #OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.book", cascade =
// CascadeType.ALL)
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk", cascade = CascadeType.ALL)
public Set<Loan> getLoans() {
return loans;
}
public void setLoans(Set<Loan> loans) {
this.loans = loans;
}
}
public class Loan implements Serializable {
private static final long serialVersionUID = 144293603488149743L;
private LoanId pk = new LoanId();
private LocalDate beginDate;
private LocalDate endDate;
private LoanStatus status;
#EmbeddedId
public LoanId getPk() {
return pk;
}
public void setPk(LoanId pk) {
this.pk = pk;
}
#Column(name = "BEGIN_DATE", nullable = false)
public LocalDate getBeginDate() {
return beginDate;
}
public void setBeginDate(LocalDate beginDate) {
this.beginDate = beginDate;
}
#Column(name = "END_DATE", nullable = false)
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
#Enumerated(EnumType.STRING)
#Column(name = "STATUS")
public LoanStatus getStatus() {
return status;
}
public void setStatus(LoanStatus status) {
this.status = status;
}
}
#Embeddable
public class LoanId implements Serializable {
private static final long serialVersionUID = 3912193101593832821L;
private Book book;
private Customer customer;
private LocalDateTime creationDateTime;
public LoanId() {
super();
}
public LoanId(Book book, Customer customer) {
super();
this.book = book;
this.customer = customer;
this.creationDateTime = LocalDateTime.now();
}
#ManyToOne
public Book getBook() {
return book;
}
public void setBook(Book bbok) {
this.book = bbok;
}
#ManyToOne
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
#Column(name = "CREATION_DATE_TIME")
public LocalDateTime getCreationDateTime() {
return creationDateTime;
}
public void setCreationDateTime(LocalDateTime creationDateTime) {
this.creationDateTime = creationDateTime;
}
}
#Table(name = "CUSTOMER")
public class Customer {
private Integer id;
private String firstName;
private String lastName;
private String job;
private String address;
private String email;
private LocalDate creationDate;
Set<Loan> loans = new HashSet<Loan>();
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "CUSTOMER_ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "FIRST_NAME", nullable = false)
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name = "LAST_NAME", nullable = false)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Column(name = "JOB")
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
#Column(name = "ADDRESS")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
#Column(name = "EMAIL", nullable = false, unique = true)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "CREATION_DATE", nullable = false)
public LocalDate getCreationDate() {
return creationDate;
}
public void setCreationDate(LocalDate creationDate) {
this.creationDate = creationDate;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.customer", cascade = CascadeType.ALL)
public Set<Loan> getLoans() {
return loans;
}
public void setLoans(Set<Loan> loans) {
this.loans = loans;
}
}
public class Category {
public Category() {
}
public Category(String code, String label) {
super();
this.code = code;
this.label = label;
}
private String code;
private String label;
#Id
#Column(name = "CODE")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Column(name = "LABEL", nullable = false)
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
#Repository
public interface ICategoryDao extends JpaRepository<Category, Integer> {
}
public interface ICustomerDao extends JpaRepository<Customer, Integer> {
public Customer findCustomerByEmailIgnoreCase(String email);
public List<Customer> findCustomerByLastNameIgnoreCase(String lastName);
}
I can't see where is the problem of my oneTomany annotation
Anyone can, i help me.

Spring doesn't save List in oneToMany relationship

I've this Address Entity
package com.appdeveloperblog.app.ws.io.entity;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Entity(name = "addresses")
public class AddressEntity implements Serializable {
private static final long serialVersionUID = 3652691377296902875L;
#Id
#GeneratedValue
private long id;
#Column(length = 30, nullable = false)
private String addressId;
#Column(length = 15, nullable = false)
private String city;
#Column(length = 15, nullable = false)
private String country;
#Column(length = 100, nullable = false)
private String streetName;
#Column(length = 7, nullable = false)
private String postalCode;
#Column(length = 10, nullable = false)
private String type;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "users_id")
private UserEntity userDetails;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAddressId() {
return addressId;
}
public void setAddressId(String addressId) {
this.addressId = addressId;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public UserEntity getUserDetails() {
return userDetails;
}
public void setUserDetails(UserEntity userDetails) {
this.userDetails = userDetails;
}
}
and this a Users Entity
package com.appdeveloperblog.app.ws.io.entity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = -3772691377276902875L;
#Id
#GeneratedValue
private long id;
#Column(nullable = false)
private String userId;
#Column(nullable = false, length = 50)
private String firstName;
#Column(nullable = false, length = 50)
private String lastName;
#Column(nullable = false, length = 120, unique = true)
private String email;
#Column(nullable = false)
private String encryptedPassword;
private String emailVerificationToken;
#Column(nullable = false)
private Boolean emailVerificationStatus = false;
#OneToMany(mappedBy = "userDetails", cascade = CascadeType.ALL)
private List<AddressEntity> addresses;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public String getEmailVerificationToken() {
return emailVerificationToken;
}
public void setEmailVerificationToken(String emailVerificationToken) {
this.emailVerificationToken = emailVerificationToken;
}
public Boolean getEmailVerificationStatus() {
return emailVerificationStatus;
}
public void setEmailVerificationStatus(Boolean emailVerificationStatus) {
this.emailVerificationStatus = emailVerificationStatus;
}
}
and this function which I use it in service layer to save the data into the Mysql Database
#Override
public UserDto createUser(UserDto user) {
if (userRepository.findByEmail(user.getEmail()) != null)
throw new RuntimeException("Record already exists");
for(int i = 0 ; i < user.getAddresses().size() ; i++)
{
AddressDTO address = user.getAddresses().get(i);
address.setUserDetails(user);
address.setAddressId(utils.generateAddressId(30));
user.getAddresses().set(i, address);
}
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = modelMapper.map(user, UserEntity.class);
String publicUserId = utils.generateUserId(30);
userEntity.setUserId(publicUserId);
userEntity.setEncryptedPassword(bCryptPasswordEncoder.encode(user.getPassword()));
UserEntity storedUserDetails = userRepository.save(userEntity);
// BeanUtils.copyProperties(storedUserDetails, returnValue);
UserDto returnValue = modelMapper.map(storedUserDetails, UserDto.class);
return returnValue;
}
after I post the data to the API using Postman POST request it save only the data into the users table and all the data in addresses table have been igonred
POST request Example:
{
"firstName" : "Sergey",
"lastName" : "Kargopolov",
"email" : "tno#test.com",
"password" : "123",
"addresses":[
{
"city":"Vancouver",
"country":"Canada",
"streetName":"123 Street name",
"postalCode": "ABCBA",
"type":"billing"
}
]
}
Below classes are the stripped down version of what you are trying to achieve. Please compare with your classes and it should work fine only difference is I have remove additional fields to test it easily. Check code in UserController map method.
UserEntity.java
#Entity
#Table(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 4865903039190150223L;
#Id
#GeneratedValue
private long id;
#Column(length = 50, nullable = false)
private String firstName;
#Column(length = 50, nullable = false)
private String lastName;
#OneToMany(mappedBy = "userDetails", cascade = CascadeType.ALL)
private List<AddressEntity> addresses;
public long getId() {
return id;
}
public void setId(long 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 List<AddressEntity> getAddresses() {
return addresses;
}
#Override
public String toString() {
return "UserEntity [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", addresses="
+ addresses + "]";
}
public void setAddresses(List<AddressEntity> addresses) {
this.addresses = addresses;
}
}
AddressEntity.java
#Entity(name = "addresses")
public class AddressEntity implements Serializable {
private static final long serialVersionUID = 3652691377296902875L;
#Id
#GeneratedValue
private long id;
#Column(length = 15, nullable = false)
private String city;
#Column(length = 15, nullable = false)
private String country;
#JsonIgnore
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "users_id")
private UserEntity userDetails;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public UserEntity getUserDetails() {
return userDetails;
}
public void setUserDetails(UserEntity userDetails) {
this.userDetails = userDetails;
}
#Override
public String toString() {
return "AddressEntity [id=" + id + ", city=" + city + ", country=" + country + "]";
}
}
UserDto.java
public class UserDto implements Serializable {
private static final long serialVersionUID = 6835192601898364280L;
private long id;
private String firstName;
private String lastName;
private List<AddressDTO> addresses;
public long getId() {
return id;
}
public void setId(long 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 List<AddressDTO> getAddresses() {
return addresses;
}
public void setAddresses(List<AddressDTO> addresses) {
this.addresses = addresses;
}
}
AddressDTO.java
public class AddressDTO {
private long id;
private String city;
private String country;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
UserController.java
#RestController
public class UserController {
#Autowired
UserRepository repository;
#PostMapping("map")
#ResponseBody
public UserEntity map(#RequestBody UserDto userDto) {
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = modelMapper.map(userDto, UserEntity.class);
for (AddressEntity address : userEntity.getAddresses()) {
address.setUserDetails(userEntity);
}
repository.save(userEntity);
return userEntity;
}
}
Sample Request:
{
"firstName" : "Sergey",
"lastName" : "Kargopolov",
"addresses":[
{
"city":"Vancouver",
"country":"Canada"
}
]
}
Output:
{
"id": 7,
"firstName": "Sergey",
"lastName": "Kargopolov",
"addresses": [
{
"id": 8,
"city": "Vancouver",
"country": "Canada"
}
]
}

Lazy fetch elements

I'm fetching Company along with productSLA using join fetch query, since the Company has userlist and it doesn't get initialized. Therefore at the time when i send response using responseentity.ok it throws lazy init exception. I don't want user list for that purpose is there any way i can send it to front end without getting lazy init exception some one suggested me to do this using dto.
I am using angular on front end. When i was using jsp i never faced this kind of problem.
#Entity
#Table(name = "USER_TABLE")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch=FetchType.EAGER)
private List<Ticket> raisedTickets;
#NotNull
#Column(unique = true)
#Email(message = "Invalid Email")
private String email;
#NotNull
#Column
#Length(min = 4, max = 12, message = "First name must be between 4 to 12 character long")
private String firstName;
#NotNull
#Column
#Length(min = 4, max = 12, message = "Last name must be between 4 to 12 character long")
private String lastName;
#NotNull
#Column
#Length(min = 8, max = 100, message = "Password must be 4 to 12 character long")
private String password;
#NotNull
#Column
#Length(min = 3, max = 30, message = "Company Name must be between 3 to 12 character long")
private String companyName;
#Column(name = "USER_ROLE")
#Enumerated(EnumType.STRING)
private UserRolesEnum userRole;
#ManyToOne
#JoinColumn(name = "COMPANY_ID", nullable = false)
#NotNull
private Company company;
#OneToMany(mappedBy="user", cascade=CascadeType.ALL)
private List<ProductAssociated> productAssociatedList=new ArrayList<ProductAssociated>();
public User() {
}
public User(String firstName, String lastName, String email, String password, String companyName,
UserRolesEnum role) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.companyName = companyName;
this.userRole = role;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer id) {
this.userId = id;
}
public List<Ticket> getRaisedTickets() {
return raisedTickets;
}
public void setRaisedTickets(List<Ticket> raisedTickets) {
this.raisedTickets = raisedTickets;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public UserRolesEnum getUserRole() {
return userRole;
}
public void setUserRole(UserRolesEnum userRole) {
this.userRole = userRole;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public List<ProductAssociated> getProductAssociatedList() {
return productAssociatedList;
}
public void setProductAssociatedList(List<ProductAssociated> productAssociatedList) {
this.productAssociatedList = productAssociatedList;
}
public void addProductAssociated(ProductAssociated productAssociated) {
productAssociatedList.add(productAssociated);
productAssociated.setUser(this);
}
#Entity
#Table(name="PRODUCT_SLA")
public class ProductSLA {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="SLA_ID")
private Integer slaId;
#NotNull
#Column(name="RESPONSE_TIME")
private int responseTime;
#Column(name="RESOLVE_TIME")
private int resolveTime;
#NotNull
#Column(name="PRIORITY")
#Enumerated(EnumType.STRING)
private PriorityEnum priority;
#ManyToOne
#JoinColumn(name="COMPANY_ID", nullable = false)
private Company company;
#ManyToOne
#JoinColumn(name="PRODUCT_ID", nullable = false)
private Product product;
public ProductSLA() {
super();
}
public ProductSLA(Integer slaId, int responseTime, int resolveTime, PriorityEnum priority) {
super();
this.slaId = slaId;
this.responseTime = responseTime;
this.resolveTime = resolveTime;
this.priority = priority;
}
public Integer getSlaId() {
return slaId;
}
public void setSlaId(Integer slaId) {
this.slaId = slaId;
}
public int getResponseTime() {
return responseTime;
}
public void setResponseTime(int responseTime) {
this.responseTime = responseTime;
}
public int getResolveTime() {
return resolveTime;
}
public void setResolveTime(int resolveTime) {
this.resolveTime = resolveTime;
}
public PriorityEnum getPriority() {
return priority;
}
public void setPriority(PriorityEnum priority) {
this.priority = priority;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
#Entity
#Table(name = "COMPANY_TABLE")
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "COMPANY_ID")
private Integer companyId;
#NotNull
#Column(name = "COMPANY_NAME", unique = true)
private String companyName;
#NotNull
#Column(name = "ADDRESS_LINE1")
private String addressLine1;
#Column(name = "ADDRESS_LINE2")
private String addressLine2;
#NotNull
#Column(name = "CITY")
private String city;
#NotNull
#Column(name="STATE_NAME")
private String state;
#NotNull
#Column(name = "COUNTRY")
private String country;
#NotNull
#Column(name = "PHONE")
private String phone;
#NotNull
#Column(name = "POSTAL_CODE")
private String postalCode;
#NotNull
#Column(name = "COMPANY_WEBSITE")
private String companyWebsite;
#OneToMany( mappedBy = "company", cascade = CascadeType.ALL)
private List<User> userList = new ArrayList<User>();
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
private List<ProductSLA> productSLAList = new ArrayList<ProductSLA>();
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval=true)
private List<AccessLevel> accessLevelList=new ArrayList<AccessLevel>();
public Company() {
super();
}
public Company(Integer companyId, String companyName, String addressLine1, String addressLine2, String city,
String state, String country, String phone, String postalCode, String companyWebsite) {
super();
this.companyId = companyId;
this.companyName = companyName;
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
this.city = city;
this.state = state;
this.country = country;
this.phone = phone;
this.postalCode = postalCode;
this.companyWebsite = companyWebsite;
}
public Integer getCompanyId() {
return companyId;
}
public void setCompanyId(Integer companyId) {
this.companyId = companyId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCompanyWebsite() {
return companyWebsite;
}
public void setCompanyWebsite(String companyWebsite) {
this.companyWebsite = companyWebsite;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public void addUser(User user) {
userList.add(user);
user.setCompany(this);
}
public List<ProductSLA> getProductSLAList() {
return productSLAList;
}
public void setProductSLAList(List<ProductSLA> productSLAList) {
this.productSLAList = productSLAList;
}
public void addProductSLA(ProductSLA productSLA) {
productSLAList.add(productSLA);
productSLA.setCompany(this);
}
public List<AccessLevel> getAccessLevelList() {
return accessLevelList;
}
public void setAccessLevelList(List<AccessLevel> accessLevelList) {
this.accessLevelList = accessLevelList;
}
public void addAccessLevel(AccessLevel accessLevel) {
accessLevelList.add(accessLevel);
accessLevel.setCompany(this);
}
}
edit
i found solutions but i am confused which one to use and how to use, because there are many solutions there.
Avoid Jackson serialization on non fetched lazy objects
Assuming your hibernate session is closed already in the controller (which is a fair assumption to make since we don't want to expose our hibernate sessions outside spring/hibernate layer) you will run into this type of problem if you try to access a collection which was not loaded when it was inside the session.
Alright!
I'm also assuming that you are returning a one or collection of "hibernate managed entities" as opposed to DTOs. What I'm sensing is that when that entity is converted into JSON all the getters are called by underlying framework unless they are marked 'ignore' (or something like that). OR may be your UI is calling userList at which point it's throwing exception since a proxy was returned by hibernate.
Regardless, it's better to return a DTO and populate it however way you like. There are various reasons why returning a DTO (or a collection of DTOs) is preferred over returning an entity.
To resolve this problem, i've used http message converter,
Application Configuration looks like this:
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
and
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate5Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
Dependency Required
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.7</version>
</dependency>
There is a dirty solution also for this,if you are willing to modify every getters:
jackson 2 object to json ignore lazy loading

Spring Hibernate lazy load behavior

I am making a web based app in spring/hibernate. In database I am using onetomany and manytoone relations. I have manytoone relationship in users for location and onetomany relationship for users in location. In both entities I have lazy loading option turned on. As per my understanding if this is turned on, the database query to get the location should not be executed until explicitly called for it but whenever I do a get from the userdao the below query is executed which makes me think that even after having the lazy option turned on it is retrieving the location information. Can anyone let me know what am I doing wrong or is this the expected behavior.
Below is my user entity code
package com.kwisque.database.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
#Entity
#Table(name = "USERS")
public class User implements Serializable{
#Id
#Column(name = "USER_ID", unique = true, nullable = false)
private String userId;
#Column(name = "NAME", nullable = true, length = 32)
private String name;
#Column(name = "PASSWORD", nullable = false, length = 64)
private String password;
#Column(name = "EMAIL_ID", nullable = true, length = 128)
private String emailId;
#Column(name = "ACTIVE", nullable = false, length = 1)
private Integer active;
#Column(name = "PROVIDER", nullable = false, length = 32)
private String provider;
#ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
#JoinTable(
name = "USER_ROLE",
joinColumns = #JoinColumn(name = "USER_ID"),
inverseJoinColumns = #JoinColumn(name = "ROLE_ID")
)
private Set<Role> roles = new HashSet<>();
//#ManyToOne(fetch = FetchType.LAZY)
//#JoinColumn(name = "LOCATION_ID", nullable = true)
#ManyToOne(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL})
#JoinTable(name="USER_LOCATION_INFO",
joinColumns={#javax.persistence.JoinColumn(name="USER_ID")},
inverseJoinColumns={#javax.persistence.JoinColumn(name="LOCATION_ID")})
private Location location;
// #OneToMany(fetch = FetchType.LAZY)
// #JoinColumn(name = "SPECIALIZATION_ID", nullable = true)
#OneToMany(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL})
#JoinTable(name="USER_SPECIALIZATION_INFO",
joinColumns={#javax.persistence.JoinColumn(name="USER_ID")},
inverseJoinColumns={#javax.persistence.JoinColumn(name="SPECIALIZATION_ID")})
private Set<Specialization> specialization = new HashSet<>();
public User() {
}
public User(final String userId, final String name, final String password, final String emailId, final Integer active, final String provider, final Set<Role> roles, final Location location) {
this.userId = userId;
this.name = name;
this.password = password;
this.emailId = emailId;
this.active = active;
this.provider = provider;
this.roles = roles;
this.location = location;
}
public String getUserId() {
return userId;
}
public void setUserId(final String userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public Integer getActive() {
return active;
}
public void setActive(final Integer active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(final Set<Role> roles) {
this.roles = roles;
}
public String getProvider() {
return provider;
}
public void setProvider(final String provider) {
this.provider = provider;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(final String emailId) {
this.emailId = emailId;
}
public Location getLocation() {
return location;
}
public void setLocation(final Location location) {
this.location = location;
}
}
Location entity code
package com.kwisque.database.model;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name = "LOCATION")
public class Location implements Serializable {
private static final long serialVersionUID = -7153748534015057865L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "LOCATION_ID", unique = true, nullable = false)
private Integer locationId;
#Column(name = "ZIP_CODE", nullable = true, length = 132)
private String zipCode;
#Column(name = "STATE_ABBR", nullable = true, length = 132)
private String stateAbbr;
#Column(name = "LATITUDE", nullable = true, length = 132)
private double latitude;
#Column(name = "LONGITUDE", nullable = true, length = 132)
private double longitude;
#Column(name = "CITY", nullable = true, length = 132)
private String city;
#Column(name = "STATE", nullable = true, length = 132)
private String state;
#JsonIgnore
#OneToMany(fetch = FetchType.LAZY, mappedBy = "location")
private Set<User> users;
public double getLatitude() {
return this.latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return this.longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public Location() {
}
public Location(Integer locationId, long longitude, String city, long latitude, String zipCode, String state,
String stateAbbr, Set<User> users) {
this.locationId = locationId;
this.longitude = longitude;
this.latitude = latitude;
this.city = city;
this.state = state;
this.stateAbbr = stateAbbr;
this.users = users;
}
public Integer getLocationId() {
return this.locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
#JsonIgnore
public Set<User> getUser() {
return this.users;
}
#JsonIgnore
public void setUser(Set<User> users) {
this.users = users;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getZipCode() {
return this.zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getStateAbbr() {
return this.stateAbbr;
}
public void setStateAbbr(String stateAbbr) {
this.stateAbbr = stateAbbr;
}
}
Query being executed at my get from USerDao
Hibernate: select user0_.USER_ID as USER_ID1_3_0_, user0_.ACTIVE as ACTIVE2_3_0_, user0_.EMAIL_ID as EMAIL_ID3_3_0_, user0_.NAME as NAME4_3_0_, user0_.PASSWORD as PASSWORD5_3_0_, user0_.PROVIDER as PROVIDER6_3_0_, user0_1_.LOCATION_ID as LOCATION1_4_0_, roles1_.USER_ID as USER_ID1_3_1_, role2_.ROLE_ID as ROLE_ID2_5_1_, role2_.ROLE_ID as ROLE_ID1_1_2_, role2_.NAME as NAME2_1_2_ from USERS user0_ left outer join USER_LOCATION_INFO user0_1_ on user0_.USER_ID=user0_1_.USER_ID left outer join USER_ROLE roles1_ on user0_.USER_ID=roles1_.USER_ID left outer join ROLE role2_ on roles1_.ROLE_ID=role2_.ROLE_ID where user0_.USER_ID=?

Resources