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

I have an unidirectional OneToMany JPA entity mapping in my (Spring Framework + Spring Data + Hibernate JPA) project. Entity classes are like in the following code.(I have removed irrelevant class members for brevity).
#Entity
#Table(name = "employees")
class Employee{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "employee_id")
private List<DepartmentAssignment> departmentAssignments = new ArrayList<>();
}
#Entity
#Table(name = "department_assignments")
class DepartmentAssignment{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#NotNull
#Column(name = "employee_id")
private Integer employeeId;
#NotNull
#Column(name = "department_id")
private Integer departmentId;
}
#Entity
#Table(name = "departments")
class Department{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
}
And, in one of my service classes have a method to remove a DepartmentAssignment from an Employee like below.
public Employee deleteDepartmentAssignment(Integer empId, Integer deptAssignmentId) {
Employee employee = employeeRepository.findOne(empId);
if(employee != null) {
for ( DepartmentAssignment da : employee.getDepartmentAssignments()) {
if(da.getId().equals(deptAssignmentId)) {
employee.getDepartmentAssignments().remove(da);
employee = employeeRepository.save(employee);
break;
}
}
}
return employee;
}
However, calling above methods gives me an error: org.hibernate.exception.ConstraintViolationException ,and in the SQL log, I can see Column 'employee_id' cannot be null error for the last SQL statement of the transaction.
Can anybody tell me what I'm doing wrong here and how to get it fixed?

You don't need to add
#NotNull
#Column(name = "employee_id")
private Integer employeeId;
to the Employee, if you use #JoinColumn(name = "employee_id"). Try to remove it.

You can try the following, not sure why you use the plain id in the object. Thats not object relational mapping.
For more details see Hibernate triggering constraint violations using orphanRemoval
#Entity
#Table(name = "employees")
class Employee{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "employee", orphanRemoval = true)
private List<DepartmentAssignment> departmentAssignments = new ArrayList<>();
}
#Entity
#Table(name = "department_assignments")
class DepartmentAssignment{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(optional=false)
private Employee employee;
#ManyToOne(optional=false)
private Department department;
}
#Entity
#Table(name = "departments")
class Department{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
}

You must look .hbm.xml file and you should mapping your Entity in this file and
you can look this example
http://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example/
I hope it will be useful for you.

try removing
cascade = CascadeType.ALL
but im not 100% sure..

Related

JPA onetomany mapping showing nested data many times

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

JPA do not allow binary one to many relationship

I have 2 entities as below:
Course
#Entity
public class Course {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "course", cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE})
private List<Comment> comments;
Comment
#Entity
public class Comment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String comment;
#ManyToOne(targetEntity = Course.class)
private Course course; //Error: 'Many To One' attribute type should not be 'Course'
I follow luv2code.com course but he use Spring MVC and it work just find, but when I do this in spring boot, it always show the error, please help me fix this!
Try something like this:
#Entity
public class Course {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "course")
private List<Comment> comments;
And your comment entity:
#Entity
public class Comment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String comment;
#ManyToOne(cascade = CascadeType.ALL)
private Course course;
#Entity
public class Course {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
orphanRemoval = true)
private List<Comment> comments = new ArrayList<Comment>();
#Entity
public class Comment {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String comment;
}
You don't to define ManyToOne Mapping in your comment Entity.

Spring Boot JPA Fetch Parent & Child

I have 2 tables:
#Entity
#Table
public class ProductEntity extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long productId;
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<ProductItemEntity> productItems;
}
#Entity
#Table
public class ProductItemEntity extends AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long itemId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PRODUCT_ID", nullable = false)
private ProductEntity product;
#Column(name="PRODUCT_RATE") // Unique
private Integer productRate;
}
I am trying to run a test where I am querying by productId and productRate, which is as follow:
#Query("SELECT p FROM ProductEntity p JOIN FETCH p.productItems pi WHERE p.productId = :productId AND pi.productRate = :rate ")
ProductEntity findByProductAndRate(#Param("productId") Long productId, #Param("rate") Integer rate);
I save a product and product item first. Then execute above method to get the product with product item. But I get null result.
Don't know if I am missing something. Any help would be appreciated.
Spring Boot
H2 (#DataJpaTest)

SQL error or missing database / OneToMany SQLIte-Spring Boot

I have a problem with the relationship oneToMany. I created tables in SQLite DB, this is my tables:
My CategoryModel:
#Entity
#Table(name = "Category")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class CategoryModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String category_name;
private String category_description;
private String image_path;
#JsonIgnore
#OneToMany( mappedBy = "category")
private Set<ProductModel> category;
My ProducCategory:
#Entity
#Table(name = "Product_Category")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class ProductModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long product_id;
private Long category_id;
private String name;
private String description;
private int numberOfProduct;
private String image;
private int price;
#ManyToOne
#JoinColumn(name = "country_id", nullable = false)
private CategoryModel category;
I can get data from the Category table well but when I call data from the Product_Category table I have the error:
SQL error or missing database (no such column: productmod0_.country_id)
country_id does not exist anywhere in your tables.
What you want is : #JoinColumn(name = "category_id", nullable = false)

Return an empty list on #OneToMany SpringBoot - Hibernate

I am getting null when using relationship in hibernate.
Here is my code
User entity
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long userId;
#OneToMany(mappedBy="user",targetEntity=LoginHistory.class, fetch=FetchType.LAZY,cascade = CascadeType.ALL)
private List<LoginHistory> loginHistory = new ArrayList<LoginHistory>();
LoginHistory Entity
#Entity
#Table(name = "login_history")
public class LoginHistory {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#ManyToOne(cascade = CascadeType.DETACH)
#JoinColumn(name="userId",referencedColumnName="id")
private User user;
To get login history details
#Override
public List<LoginHistory> getLoginHistory(User user) {
List<LoginHistory> lst = user.getLoginHistory();
return lst;
}
I am getting an empty list. Please help
it is working as designed as you are accessing an entity which is lazy loaded.Use the below like code to get the login history if you continue to keep the lazy loading on.
User user = getByKey(id);
if(user!=null){
Hibernate.initialize(user.getUserProfiles());
}

Resources