#GeneratedValue annotation is not working on mapping table - spring

I have a many to many relationship like below.
#Entity
#Table(name = "employees")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "EMP_ID")
private int id;
private String firstName;
private String lastName;
#JoinTable(name = "employee_project_mapping", joinColumns = #JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "EMP_ID"), inverseJoinColumns = #JoinColumn(name = "PROJECT_ID", referencedColumnName = "PJT_ID"))
#JsonManagedReference
#ManyToMany(cascade = CascadeType.ALL)
Set<Project> projects = new HashSet<Project>();
.....
.....
}
#Entity
#Table(name = "projects")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PJT_ID")
private int projectId;
private String projectName;
private int teamSize;
#ManyToMany(mappedBy = "projects")
#JsonBackReference
private Set<Employee> emps = new HashSet<Employee>();
.....
.....
}
#Entity
#Table(name = "employee_project_mapping")
public class EmployeeProjectMapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "EMP_PJT_ID")
private Integer empPjtId;
#Column(name = "PROJECT_ID")
private Integer projectId;
#Column(name = "EMPLOYEE_ID")
private Integer emploeeId;
.....
.....
}
But when I am trying to insert an employee object with set of projects, it is failing to create auto generated id for the column EMP_PJT_ID (this is an id to the mapping table record). Can't I add an auto generated id for mapping table using jpa?
Error trace
Hibernate: insert into employees (emp_id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into employee_project_mapping (employee_id, project_id) values (?, ?)
2021-04-22 23:34:25.973 ERROR 24126 --- [nio-8080-exec-9] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "EMP_PJT_ID"; SQL statement:
insert into employee_project_mapping (employee_id, project_id) values (?, ?) [23502-200]
2021-04-22 23:34:25.975 ERROR 24126 --- [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: NULL not allowed for column "EMP_PJT_ID"; SQL statement:
insert into employee_project_mapping (employee_id, project_id) values (?, ?) [23502-200]

The mapping of a many-to-many should be:
#Entity
#Table(name = "employees")
public class Employee {
...
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, orphanRemoval = true)
Set<EmployeeProjectMapping> projects = new HashSet<EmployeeProjectMapping>();
...
// Utility method to update both sides of the association
public void addProject(Project project) {
EmployeeProjectMapping empProject = new PersEmployeeProjectMappingonAddress( this, project );
projects.add( empProject );
project.getEmployees().add( empProject );
}
}
#Entity
#Table(name = "projects")
public class Project {
...
#OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<EmployeeProjectMapping> emps = new HashSet<Employee>();
...
}
#Entity
#Table(name = "employee_project_mapping")
public class EmployeeProjectMapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "EMP_PJT_ID")
private Integer empPjtId;
#Id
#ManyToOne
#JoinColumn(name = "PROJECT_ID")
private Project project;
#Id
#ManyToOne
#JoinColumn(name = "EMPLOYEE_ID")
private Employee employee;
.....
.....
}
Make sure to check the example on the Hibernate ORM documentation for all the details.

Related

ERROR: syntax error at or near "." - JPA Pageable

repository:
#Repository
public interface PostRepository extends PagingAndSortingRepository<Post, Long> {
#Query(value = "SELECT p.postComments FROM Post p WHERE p.webId = ?1")
Page<PostComment> findCommentsByWebId(String webid, Pageable pageable);
}
Post entity:
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "web_id")
private String webId;
#Column(nullable = false, name = "title")
private String title;
#Column(nullable = false, name = "description")
private String description;
#Column(nullable = false, name = "mature")
private boolean mature;
#OneToOne(mappedBy = "post")
private Cover cover;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#OneToMany(mappedBy = "post")
private List<PostView> postViews;
#ManyToMany
#JoinTable(name = "post_tag",
joinColumns = #JoinColumn(name = "post_id"),
inverseJoinColumns = #JoinColumn(name = "tag_id"))
private List<Tag> tags;
#OneToMany(mappedBy = "post")
private List<PostDownvote> postDownvotes;
#OneToMany(mappedBy = "post")
private List<PostUpvote> postUpvotes;
#OneToMany(mappedBy = "post")
private List<PostComment> postComments;
#Column(name = "created_at")
private Timestamp createdAt;
#Column(name = "updated_at")
private Timestamp updatedAt;
}
The problem: When returning plain List<PostComment> from the query method everything works fine. But if I change it to Page<PostComment> (I need total elements count), I get the following error:
2022-08-03 22:29:41.399 ERROR 9192 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: syntax error at or near "."
Position: 14
Hibernate: select tags0_.post_id as post_id1_6_0_, tags0_.tag_id as tag_id2_6_0_, tag1_.id as id1_10_1_, tag1_.name as name2_10_1_ from post_tag tags0_ inner join tag tag1_ on tags0_.tag_id=tag1_.id where tags0_.post_id=?
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
It is very difficult to debug this. Does anyone have any clue on what is wrong?
I need BOTH paging and total amount of elements.
Basically you are not able to fetch the part of the inner collection. But you could reach it from the another side of the bi-directional relationship
#Repository
public interface PostCommentRepository extends PagingAndSortingRepository<PostComment, Long> {
#Query(value = "SELECT pc FROM PostComment pc WHERE pc.post.webId = ?1")
Page<PostComment> findCommentsByWebId(String webid, Pageable pageable);
// or better using Spring Data naming conventions just
Page<PostComment> findAllByPostWebId(String webid, Pageable pageable);
}
If you only need a total count you should avoid querying list of entities which could be very memory intensive.
So in your PostCommentRepository try the following:
long countAllByPost_WebId(String webId);

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)

Why OneToMany JPA association is failing while insert statement executes

Hi below is my schema definition
CREATE TABLE LOANS (
LOAN_ID NUMBER(9,0) PRIMARY KEY,
CORR_ID VARCHAR(5) NULL
);
CREATE TABLE DV_LOAN_PARTICIPANTS (
LOAN_ID NUMBER(9,0) ,
DVP_PARTICIPANT_NAME VARCHAR(50) NOT NULL,
DVP_PARTICIPANT_TYPE VARCHAR(50) NOT NULL,
PRIMARY KEY ("LOAN_ID", "DVP_PARTICIPANT_NAME")
);
LOANS Entity
#Table(name = "LOANS")
#Entity
public class Loans {
#Id
#Column(name = "LOAN_ID")
private Long loanId;
#OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "LOAN_ID")
#MapKey(name = "dvpParticipantName")
private Map<String, DVLoanParticipants> dvLoanParticipantsMap;
// getter and setters
}
DV_LOAN_PARTICIPANTS Entity
#Table(name = "DV_LOAN_PARTICIPANTS")
#Entity
public class DVLoanParticipants implements Serializable {
#Id
#Column(name = "LOAN_ID")
private Long loanId;
#Id
#Column(name = "DVP_PARTICIPANT_NAME")
private String dvpParticipantName;
#Column(name = "DVP_PARTICIPANT_TYPE")
private String dvpParticipantType;
// getters and setters
}
Service Class is
DVLoanParticipants dvLoanParticipants = new DVLoanParticipants();
dvLoanParticipants.setLoanId(Long.valueOf("196801758"));
dvLoanParticipants.setDvpParticipantName("VKP");
dvLoanParticipants.setDvpParticipantType("Developer");
Loans loanInsert = new Loans();
loanInsert.setLoanId(Long.valueOf("196801758"));
Map<String,DVLoanParticipants> partyMap = new HashMap<>();
partyMap.put("VKP",dvLoanParticipants);
loanInsert.setDvLoanParticipantsMap(partyMap);
repository.save(loanInsert);
But when i am executing the save i am getting error as
NULL not allowed for column "LOAN_ID"; SQL statement:
insert into dv_loan_participants (dvp_participant_type, loan_id, dvp_participant_name) values (?, ?,
?)
Git Hub Code
https://github.com/vinoykp/spring-jpa/tree/master/spring-boot-hibernate-crud-demo
I had the similar question
Why Value is not getting assigned in JPA for insert statement
What is the issue in association?

ERROR: UPDATE or DELETE statement on table

In a project with Spring Boot and Spring JPA I Have two entities FunctionConfiguration and InvokeFunctionResult.
#Entity
#Table(name = "function_configuration")
public class FunctionConfigurationEntity {
#Id
#Column(name = "id_function_configuration")
#GeneratedValue(strategy = IDENTITY)
private Integer idFunctionConfiguration;
}
#Entity
#Table(name = "invoked_function_result")
public class InvokedFunctionResultEntity {
#Id
#Column(name = "id_invoked_result_function")
#GeneratedValue(strategy = IDENTITY)
private Integer idInvokedResultFunction;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "function_configuration_id", nullable = false, foreignKey = #ForeignKey(name = "function_configuration_fk"), referencedColumnName = "id_function_configuration")
private FunctionConfigurationEntity functionConfiguration;
}
The InvokeFunctionResult has foreign key the id of the FunctionConfiguration.
If I try to do a delete with an id of a functionConfiguration that is present in the InvokeFunctionResult:
#Transactional
#Modifying
#Query(value = "DELETE FROM FunctionConfigurationEntity fce WHERE fce.idFunctionConfiguration = idFunctionConfiguration")
void deleteByFunctionConfigurationId(#Param("idFunctionConfiguration") Integer functionConfigurationId);
I get the following error: Caused by: org.postgresql.util.PSQLException: ERROR: UPDATE or DELETE statement on table "function_configuration" violates foreign key constraint "function_configuration_fk" on table "invoked_function_result"
How can I fix it?

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

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

Resources