why employee_id and department_id not update automatic in database Hibernate jpa - spring-boot

few days back i starting learning hibernate JPA but i am unable to find solution of given problem below
My Project consist three class employee ,phone ,department by seeing code you can easily understand what i am doing .
Main problem raise when i try to save this data into database using spring boot controller it showing null value in column . In employee table department_id is null(not automatic update using cascade.All) same in phone table employee_id is null.
I do not want update manually .is their any way so dep_id and emp_id automatic update to foreign key table .
{
"name":"CSE",
"employees":[
{
"name":"Welcome",
"age":23,
"phones":[{"number":1234567890},{"number":1234567890}]
},
{
"name":"back",
"age":25,
"phones":[{"number":1234567890},{"number":1234567890}]
}
]
}
package com.example.entity;
import javax.persistence.*;
import java.util.List;
#Entity
#Table(name = "employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private int age;
#ManyToOne
#JoinColumn(name = "department_id")
private Department department;
#OneToMany(mappedBy = "employee", cascade=CascadeType.ALL)
private List<Phone> phones;
// getters and setters...
}
package com.example.entity;
import javax.persistence.*
#Entity
public class Phone {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String number;
#ManyToOne
#JoinColumn(name = "employee_id")
private Employee employee;
// getters and setters...
}
package com.example.entity;
import javax.persistence.*;
import java.util.List;
#Entity
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
#OneToMany(mappedBy = "department",cascade = CascadeType.ALL)
private List<Employee> employees;
}
dept table in database
id name
1 CSE
employee table
id name age department_id
1. welcome 23. null
2. back. 25. null
phone table
id number employee_id
1. 1234567890. null
2. 1234567890. null
3. 1234567890 null
4. 1234567890. null
Why employee_id and department_id not updating automatic in cascade All
Controller class
package com.example.controller;
import com.example.dao.DepRepo;
import com.example.dao.EmployeeRepo;
import com.example.dao.PhoneRepo;
import com.example.entity.Department;
import com.example.entity.Employee;
import com.example.service.FakeService;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import jakarta.inject.Inject;
#Controller("/dummy")
public class DummyController {
#Inject
FakeService fakeService;
#Inject
PhoneRepo phoneRepo;
#Inject
EmployeeRepo employeeRepo;
#Inject
DepRepo depRepo;
#Get ("/")
public String fun(){
fakeService.fun();
return "welcome back";
}
#Post("/add")
public HttpResponse<?> fun(#Body Department dep){
System.out.println(dep);
depRepo.save(dep);
return HttpResponse.status(HttpStatus.ACCEPTED).body("data add successfully");
}
}

Your Hibernate mapping says that the relationships are mapped by the 'many' side of the association:
#OneToMany(mappedBy = "department",cascade = CascadeType.ALL)
private List<Employee> employees;
So Hibernate looks for the value of the 'department' in the employee entity and it is null (because there's no value in the JSON data)
So try removing mappedBy to tell Hibernate that the relationship is mapped on the 'one' side

Related

No property .. found for type .. in spring boot

I'm a beginner with spring and I have this little issue. "No property questionId found for type CourseTestCompleteField!" I have 2 model classes that are connected via a one to one join.
That 2 model class are:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "questions")
public class CourseTestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="question_id")
private Long id;
#NotBlank
#Column(name = "question_course")
private String questionCourse;
#NotBlank
#Column(name = "question_type")
private String questionType;
public CourseTestQuestion(){
}
public CourseTestQuestion(String questionCourse, String questionType) {
this.questionCourse = questionCourse;
this.questionType = questionType;
}
// public getters and setters for all fields here
}
And:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "quiz_complete_field_questions",
uniqueConstraints = {
#UniqueConstraint(columnNames = "question_id")
}
)
public class CourseTestCompleteField {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "question_content")
private String questionContent;
#NotBlank
#Column(name = "answer")
private String answer;
#NotBlank
#Column(name = "points")
private String points;
#NotBlank
#Column(name = "course")
private String course;
#NotBlank
#Column(name = "teacher_username")
private String teacher;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "question_id", referencedColumnName = "question_id")
private CourseTestQuestion courseTestQuestion;
public CourseTestCompleteField(){
}
public CourseTestCompleteField(CourseTestQuestion courseTestQuestion, String question, String answer, String points, String course, String teacher) {
this.courseTestQuestion = courseTestQuestion;
this.questionContent = question;
this.answer = answer;
this.points = points;
this.course = course;
this.teacher = teacher;
}
// public getters and setters for all fields here
}
My repo for both:
package com.example.springboot.repository;
import com.example.springboot.models.Course;
import com.example.springboot.models.CourseTestQuestion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface CourseTestQuestionRepository extends JpaRepository<CourseTestQuestion, Long> {
Optional<CourseTestQuestion> findById(Long id);
Optional<CourseTestQuestion> findByQuestionCourse(String questionCourse);
}
And:
package com.example.springboot.repository;
import com.example.springboot.models.CourseTestCompleteField;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
#Repository
public interface CourseTestCompleteFieldRepository extends JpaRepository<CourseTestCompleteField, Long> {
Optional<CourseTestCompleteField> findById(Long id);
Optional<CourseTestCompleteField> findByQuestionId(Long questionId);
Optional<CourseTestCompleteField> findByCourse(String course);
List<CourseTestCompleteField> findByQuestionContent(String questionContent);
List<CourseTestCompleteField> findByTeacher(String teacher);
Boolean existsByQuestionContent(String questionContent);
}
The problem is with Optional<CourseTestCompleteField> findByQuestionId(Long questionId);but I don't get it why, because in database I have the table for CourseTestCompleteFieldModel with question_id column, and in CourseTestCompleteField I have CourseTestQuestion object. Tho, the table for CourseTestCompleteField has a different name, could be this a problem? I should rename the table to course_test_complete_field?
Can someone help me please? Thank you
Since,This is a query on nested Object. You need to update your query as this.
Optional<CourseTestCompleteField> findByCourseTestQuestion_Id(Long questionId);
This works even without "_"
Optional<CourseTestCompleteField> findByCourseTestQuestionId(Long questionId);
But better to put "_" while accessing nested fields for better readability.
There is no field call questionId in you entity and you have id only.
That's you got error. You can use that findyById(). That's only enough.
If you would like write JPA repository method like findBy..., getBy..., deleteBy...., countBy..., After this you need append exact field name from entity.
For example if you entity have name then can write below methods. findByName(); deleteByName(); countByName();
So try as below.
findBycourseTestQuestion(Object o);
Pass questions object.

JPA #ForeignKey(value = ConstraintMode.NO_CONSTRAINT) not working with #ManyToMany

I have two entities with ManyToMany Relationship. Goal here is to create schema when application start with no foreign key
1). Job.java
package com.govjobportalbackend.entity;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "job")
public class Job extends BasicEntity {
#Column(name = "icon")
private String icon;
#ManyToMany
#JoinTable(
name="job_city",
joinColumns = #JoinColumn(name = "job_id"),
inverseJoinColumns = #JoinColumn(name = "city_id"),
foreignKey = #ForeignKey(value = ConstraintMode.NO_CONSTRAINT),
inverseForeignKey = #ForeignKey(value = ConstraintMode.NO_CONSTRAINT)
)
private List<City> cities;
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public List<City> getCities() {
return cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
}
2). City.java
package com.govjobportalbackend.entity;
import java.util.List;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
#Entity
#DiscriminatorValue(value = "city")
public class City extends JobMetadata {
#ManyToMany(mappedBy = "cities")
private List<Job> jobs;
#Override
public List<Job> getJobs() {
return jobs;
}
#Override
public void setJobs(List<Job> jobs) {
this.jobs = jobs;
}
}
Below property is set in application.properties file
spring.jpa.hibernate.ddl-auto=update
When run the application, it is logging below SQLs in logs and is creating two foreign keys
Hibernate: create table job (id int4 not null, name varchar(255), icon varchar(255), primary key (id))
Hibernate: create table job_city (job_id int4 not null, city_id int4 not null)
Hibernate: create table job_metadata (type varchar(31) not null, id int4 not null, name varchar(255), primary key (id))
Hibernate: alter table if exists job_city add constraint FKiksm0d31mc3osxut4ciaf4uof foreign key (job_id) references job
Hibernate: alter table if exists job_city add constraint FKknw4pf63xt1tvnqrmrjrm5hqq foreign key (city_id) references job_metadata
If I annotate as per below in City.java then it works as expected but as per my "little" research, this bug is fixed in hibernate (so mapped entity is not required to be annotated with depreciated annotation), or may be I am wrong.
#ManyToMany(mappedBy = "cities")
#org.hibernate.annotations.ForeignKey(name = "none")
private List<Job> jobs;
Environment I am using is below;
Java 11
Hibernate 5.4.28.Final (spring-boot-starter-web)
As SimonMartinelli pointed out, this is most definitely a Hibernate bug. The version that worked for me was:
#JoinTable(
name="job_city",
joinColumns = #JoinColumn(name = "job_id", foreignKey = #ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT)),
inverseJoinColumns = #JoinColumn(name = "city_id", foreignKey = #ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
)
I found that the functionality breaks when you either (1) use #JoinTable.foreignKey instead, or (2) omit the name parameter.

JPA/Hibernate. How to get child objects contained in a list of Parent object using createQuery method

I have Certificate class that contains list of Tag classes
import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
#Entity
#Table(name = "gift_certificate")
public class Certificate {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private BigDecimal price;
private Integer duration;
#Column(name = "create_date")
private LocalDateTime createDate;
#Column(name = "last_update_date")
private LocalDateTime lastUpdateDate;
#ManyToMany
#JoinTable(name = "gift_certificate_tag",
joinColumns = #JoinColumn(name = "tag_id"),
inverseJoinColumns = #JoinColumn(name = "gift_certificate_id")
)
private List<Tag> tags;
getters and setters and other code...
....
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name = "tag")
public class Tag {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
getters and setters and other code...
And I'm trying to get List of Certificate from DB using JPA/Hibernate.
I'm using EntityManager
public List<Tag> getCertificateTags(Long certificateId) {
return entityManager.createQuery("select c.tags from Certificate c where c.id=:id")
.setParameter("id", certificateId)
.getResultList();
}
And it works, but I get just list, not List and IDEA is warning Unchecked assignment: 'java.util.List' to 'java.util.List<Tag>'.
And when I use createQuery with second parameter Tag.class like this:
entityManager.createQuery("select c.tags from Certificate c where c.id=:id", Tag.class)
.setParameter("id", certificateId)
.getResultList();
I get java.lang.IllegalArgumentException: Type specified for TypedQuery [Tag] is incompatible with query return type [interface java.util.Collection]
How can I fix it?
Try to change the query this way
select t from Certificate c join c.tags t where c.id=:id
The reason is that select c.tags means every result row contains a list of tags. But when you select t from Certificate c join c.tags t every row contains one tag

How to join 3 tables into one table with JPA?

I am creating an API where I have 3 tables called User, Book and Status. And I want to create a combined table User_Book_Status. I am not sure how to implement this in JPA. I think all tables have M:N relationship with each other. How should I join these 3 tables?
Here is my design for the database.
User.java
import javax.persistence.*;
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
#Column(nullable = false)
private String username;
#Column(nullable = false)
private String password;
public User() {}
//Getters and setters omitted.
}
Book.java
import javax.persistence.*;
#Entity
#Table(name = "books")
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long id;
#Column(nullable = false)
private String title;
#Column(nullable = false)
private String author;
#Column(nullable = false)
private int pages;
public Book() {}
//Getters and setters omitted.
}
Status.java
import javax.persistence.*;
#Entity
public class Status {
public enum ReadingStatus {READING,
FINISHED,
ONHOLD}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Enumerated(EnumType.STRING)
private ReadingStatus status;
}
here is an example of how to implement your solution already working:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "user_book_status")
public class UserBookStatus {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#ManyToOne
#JoinColumn(name = "book_id")
private Book book;
#ManyToOne
#JoinColumn(name = "status_id")
private Status status;
}
#Table to specify the name of the Table, so you can change the name of the entity freely.
#ManyToOne means that you can have many records of UserBookStatus for a single user, or book or status.
#JoinColumn use to specify the name of the column in your entity that maps to the #Id from the entity (User,Book,Status) you are referencing.
It seems to me that you don't really need an entity for Status. I would model it like this:
#Entity
public class Loan {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#ManyToOne
private Book book;
#ManyToOne
private User user;
#Enumerated(EnumType.STRING)
private ReadingStatus status;
//...
}
Also, you could make the relationships bidirectional, so that both User and Bookhas a list of Loans.

hibernate #ManyToOne no table relationship

Currently Using:
Hibernate 4.0.1.Final
Spring-data-jpa: 1.0.3.RELEASE
QueryDSL: 2.3.0
MySQL 5.x
I have an interesting problem that I have not found the answer, or clue for yet. I have two tables that did not have foreign key or other relationship. But to try and solve this issue I added one. I want my User entity to hold it's UserRole. This pattern is repeated throughout the database, but this is the easiest to describe.
Here are my tables:
User
userId bigint(20) PK
password varchar(255)
status int(11)
userName varchar(255)
userRoleId long
CONSTRAINT `FK_USERROLE` FOREIGN KEY (`userRoleId`) REFERENCES `UserRole` (`userRoleId`)
UserRole
userRoleId bigint(20) PK
userRoleDescription varchar(255)
userRoleDescriptionShort varchar(255)
Here are my classes:
User.java
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#XmlRootElement(name = "User")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
private String password;
private int status;
private String userName;
#ManyToOne
#JoinColumn(name = "userRoleId")
private UserRole userRole;
public UserRole getUserRole() {
return userRole;
}
public void setUserRole(UserRole userRole) {
this.userRole = userRole;
}
UserRole.java
#Entity
#XmlRootElement(name = "userRole")
public class UserRole {
private Long userRoleId;
private String userRoleDescription;
private String userRoleDescriptionShort;
#ElementCollection
#OneToMany(mappedBy = "userRole")
private List<User> users;
public UserRole() {...}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getUserRoleId() {... }
#OneToMany(mappedBy = "userRole")
public List<User> getUsers() {...}
So you can see where I am trying to associate the UserRole.userRoleId with the User. I thought perhaps Hibernate would build the mapping and retrieve/associate the UserRole whenever the User was updated.
I have gone back and edited this post to use a foreign key between the tables, but on app server startup I get this:
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.List, at table: UserRole, for columns: [org.hibernate.mapping.Column(users)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:304)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:288)
at org.hibernate.mapping.Property.isValid(Property.java:216)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:467)
at org.hibernate.mapping.RootClass.validate(RootClass.java:268)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1287)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1729)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:84)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
I looked for that error, which appears related to JPA and transient variables, which is not the case here.
If i were you i would first clean the annotations, it is forbidden to annotate BOTH getter AND fields in the same entity, it could end up in unexpected results ...
#ElementCollection
#OneToMany(mappedBy = "userRole")
private List<User> users;
#OneToMany(mappedBy = "userRole")
public List<User> getUsers() {...}
should be simplified in :
#ElementCollection
#OneToMany(mappedBy = "userRole")
public List<User> getUsers() {...}

Resources