Spring doesn't save List in oneToMany relationship - spring

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"
}
]
}

Related

How to display error message if record exists

I am trying to validate that if the email exists in my database, the error message will come out instead of the White Error Page.
I tried using this link but it is not working for me. Below are my codes.
Codes for Model Class
public class Employee {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email", unique = true)
#Email
private String email;
#Column(name = "posit")
private String position;
#Column(name = "mobile")
private String phone_num;
public Employee() {}
public Employee(String firstName, String lastName, String email, String position, String phone_num) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phone_num = phone_num;
this.position = position;
}
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 String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone_num() {
return phone_num;
}
public void setPhone_num(String phone_num) {
this.phone_num = phone_num;
}
}
Codes for EmployeeServiceInterface
public interface EmployeeService {
Employee save(Employee employee);
}
Codes for EmployeeServiceImplementation
#Service
public class EmployeeServiceImpl implements EmployeeService{
#Autowired
private EmployeeRepository employeeRepository;
#Override
public Employee save(Employee employee) {
this.employeeRepository.save(employee);
return employee;
}
public boolean exist(String email){
return employeeRepository.existsByEmail(email);
}
Controller
#Controller
public class EmployeeRegistrationController {
#Autowired
private EmployeeService employeeService;
private EmployeeServiceImpl employeeImpl;
#PostMapping("/saveEmployee")
public String saveEmployee(#ModelAttribute("employee") Employee employee) {
// save employee to database
employeeService.save(employee);
if(employeeService.exist==true){
return "User already exist";
}
return "success";
}
}

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.

Hibernate connecting table unique on columns problem

I have problem with hibernate because he creates connecting table (I don't know why will be nice if can tell me where and why), and what is worst he using unique on columns and i cant add more then one user with the same role.
Whole project: https://github.com/dextep/sms/tree/master/src/main/java/pl/popiel/sms
Database look
User.class
package pl.popiel.sms.model.user;
import org.hibernate.validator.constraints.UniqueElements;
import javax.persistence.*;
import javax.validation.constraints.Email;
import java.util.Set;
#Entity
#Table(name="sms_users")
#SequenceGenerator(name = "sms_users_seq", sequenceName = "sms_users_seq", allocationSize = 1)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sms_users_seq")
private long id;
#Email
private String email;
private String password;
private String firstName;
private String lastName;
#Column(name="mobile_nr")
private String mobileNumber;
#ElementCollection(targetClass=Role.class)
private Set<Role> roles;
public String getFullName() {
return firstName != null ? firstName.concat(" ").concat(lastName) : "";
}
public User() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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 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 getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role.class
package pl.popiel.sms.model.user;
import org.hibernate.validator.constraints.UniqueElements;
import org.springframework.stereotype.Indexed;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="sms_roles")
#SequenceGenerator(name = "sms_roles_seq", sequenceName = "sms_roles_seq", allocationSize = 1)
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sms_roles_seq")
private long id;
private String role;
public Role() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
I didn't notice that I miss the #ManyToMany annotation at 'roles' in User class.
Solve:
#ManyToMany
private Set<Role> roles;

Repeated column in mapping entity

I am using in my project JPA embedded entities.
I have this embeddable class
#Embeddable
public class Address {
private String addressLine1;
private String addressLine2;
private String city;
private String state;
private String zipCode;
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 getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
}
And I am embedding this class in here
#Entity
public class Customer implements
DomainObject{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Version
private Integer version;
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
#Embedded
private Address billingAddress;
#Embedded
private Address shippingAddress;
#OneToOne
private User user;
#Override
public Integer getId() {
return id;
}
#Override
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
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 getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Address getBillingAddress() {
return billingAddress;
}
public void setBillingAddress(Address billingAddress) {
this.billingAddress = billingAddress;
}
public Address getShippingAddress() {
return shippingAddress;
}
public void setShippingAddress(Address shippingAddress) {
this.shippingAddress = shippingAddress;
}
}
After running the project I am this is error
Repeated column in mapping entity:
theo.tziomakas.udemy.domain.Customer column: billing_address_line1 (should be mapped with insert = "false" update = "false"
You can clone my project if you want and check it yourself.
I have also tried this answer but didn't get anything.
UPDATE
I solved this error by using the AttributeOverride annotation.
#Embedded
#AttributeOverrides({
#AttributeOverride( name = "addressLine1",
column = #Column(name = "billing_address_line1")
),
#AttributeOverride( name = "addressLine2",
column = #Column(name = "billing_address_line2")
),
#AttributeOverride( name = "city",
column = #Column(name = "billing_city")
),
#AttributeOverride( name = "state",
column = #Column(name = "billing_state")
),
#AttributeOverride( name = "zipCode",
column = #Column(name = "billing_zip_code")
)
})
private Address billingAddress;
#Embedded
#AttributeOverrides({
#AttributeOverride( name = "addressLine1",
column = #Column(name = "shipping_address_line1")
),
#AttributeOverride( name = "addressLine2",
column = #Column(name = "shipping_address_line2")
),
#AttributeOverride( name = "city",
column = #Column(name = "shipping_city")
),
#AttributeOverride( name = "state",
column = #Column(name = "shipping_state")
),
#AttributeOverride( name = "zipCode",
column = #Column(name = "shipping_zip_code")
)
})
private Address shippingAddress;
So I cloned your repository and found that the problem arises because you have Embedded Address 2 times - shippingAddress and billingAddress in Customer.java
. I would recommend the using #AttributeOverride annotation to solve this issue. See this thread.
Change the Entity Fields like this.
#Embedded
#AttributeOverrides({
#AttributeOverride(name="addressLine1",column=#Column(name="billingAddressLine1")),
#AttributeOverride(name="addressLine2",column=#Column(name="billingAddressLine2")),
#AttributeOverride(name="city",column=#Column(name="billingCity")),
#AttributeOverride(name="state",column=#Column(name="billingState")),
#AttributeOverride(name="zipCode",column=#Column(name="billingZipCode")),
})
private Address billingAddress;
#Embedded
#AttributeOverrides({
#AttributeOverride(name="addressLine1",column=#Column(name="shippingAddressLine1")),
#AttributeOverride(name="addressLine2",column=#Column(name="shippingAddressLine2")),
#AttributeOverride(name="city",column=#Column(name="shippingCity")),
#AttributeOverride(name="state",column=#Column(name="shippingState")),
#AttributeOverride(name="zipCode",column=#Column(name="shippingZipCode")),
})
private Address shippingAddress;

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

Resources