findByForeign key in Spring boot - spring-boot

I have added a foreign key as such:
#ManyToOne
#JoinColumn
private UserEntity userEntity;
And my table has these columns:
CREATE TABLE `web_course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`coursename` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`user_entity_user_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK6eys4s4qx87rxo0ha68q05oc8` (`user_entity_user_id`),
CONSTRAINT `FK6eys4s4qx87rxo0ha68q05oc8` FOREIGN KEY (`user_entity_user_id`) REFERENCES `web_user` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
I would like to create a method to findByUserId in:
#Repository
public interface CourseRepository extends JpaRepository<CourseEntity, Long> {
I have tried several combinations in vain:
public CourseEntity findByUserId(int user_id)
public CourseEntity findByUserEntityUserId(int user_id)
public CourseEntity findBy_User_entity_user_id(int user_id)
I read that there is a naming convention but I can't seem to find the correct convention since I am getting:
Error creating bean with name 'courseController': Unsatisfied dependency expressed through field 'courseRepository';
Course class:
package com.finaly.projectback.entity;
import javax.persistence.Column;
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;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name = "web_course")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class CourseEntity {
#ManyToOne
#JoinColumn
private UserEntity userEntity;
public UserEntity getUserEntity() {
return userEntity;
}
public void setUserEntity(UserEntity userEntity) {
this.userEntity = userEntity;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private long id;
#Column(name = "coursename")
private String coursename;
#Column(name = "description")
private String description;
public CourseEntity() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCoursename() {
return coursename;
}
public void setCoursename(String coursename) {
this.coursename = coursename;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public CourseEntity(UserEntity userEntity, long id, String coursename, String description) {
super();
this.userEntity = userEntity;
this.id = id;
this.coursename = coursename;
this.description = description;
}
#Override
public String toString() {
return "CourseEntity [userEntity=" + userEntity + ", id=" + id + ", coursename=" + coursename + ", description="
+ description + "]";
}
}
Can someone point me in the right direction please?

Following code should work:
public CourseEntity findByUserEntity_UserId(int user_id)
Check logs to see if the course repository is instantiated or not. Error indicates controller can'be created because of the dependency issue.
Error creating bean with name courseController: Unsatisfied dependency expressed through field courseRepository

Related

Passing JSON in body spring and constructing object with foreign key

I am trying to create a basic spring API.
I have a Post class that have an attribute User user as foreign key.
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import jakarta.persistence.*;
import java.util.Objects;
#Entity
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, updatable = false)
private Long id;
private String title;
private String body;
#ManyToOne
private User user;
public Post() {
}
public Post(String title, String body) {
this.title = title;
this.body = body;
}
// Getters and Settes ...
}
Here is the User class
package com.example.demo.model;
import jakarta.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
#Entity
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, updatable = false)
private Long id;
private String name;
private Integer age;
private String email;
#OneToMany(mappedBy = "user")
private List<Post> posts = new ArrayList<Post>();
#ManyToMany
#JoinTable(name = "user_task",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "task_id"))
private List<Task> tasks = new ArrayList<Task>();
public User() {}
public User(String name, Integer age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// Getters and Settes ...
}
and here is my Post Controller
package com.example.demo.controller;
import com.example.demo.model.Post;
import com.example.demo.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping("/post")
public class PostController {
private final PostService postService;
#Autowired
public PostController(PostService postService) {
this.postService = postService;
}
#GetMapping("/all")
public List<Post> getAllPosts (){
System.out.println("3");
return postService.getAllPosts();
}
#GetMapping("/{id}")
public Post getPost(#PathVariable Long id){
System.out.println("2");
return postService.getPost(id);
}
#PostMapping("/create")
public Post createPost(#RequestBody Post post){
return postService.createPost(post);
}
}
So in the /create endpoint i am passing a json object in the body. Here is an exemple:
{
"title": "Post1",
"body": "Post1 Body",
"user": "1"
}
the user: 1 is the foreign key to user who owns the post.
Here is the full error:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.example.demo.model.User` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('1')]
I need to insert the json object into the Post table with the foreign key

JPA #OneToMany mapping inserting null values

I had a hard time with hibernate OneToMany mapping. I have googled to find the solution from morning nothing helped. Following are my code snippets.
package com.student.app.model;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
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.JsonProperty;
#Entity
#Table(name = "student")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "student_id")
private long id;
#Column(name = "student_name")
private String name;
#Column(name = "student_class")
#JsonProperty("class")
private String clazz;
#Column(name = "total_marks")
private int totalMarks;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "student")
private List<Subject> subjects;
public Student() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public int getTotalMarks() {
return totalMarks;
}
public void setTotalMarks(int totalMarks) {
this.totalMarks = totalMarks;
}
public List<Subject> getSubjects() {
return subjects;
}
public void setSubjects(List<Subject> subjects) {
this.subjects = subjects;
}
#Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", clazz=" + clazz + ", totalMarks=" + totalMarks
+ ", subjects=" + subjects + "]";
}
}
Subject.java
package com.student.app.model;
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.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "subject")
public class Subject {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "subject_id")
private long id;
#Column(name = "subject_name")
private String name;
#Column(name = "marks")
private String marks;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "student_id")
private Student student;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMarks() {
return marks;
}
public void setMarks(String marks) {
this.marks = marks;
}
#Override
public String toString() {
return "Subject [id=" + id + ", name=" + name + ", marks=" + marks + "]";
}
}
StudentRepository.java
package com.student.app.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.student.app.model.Student;
#Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
Student findStudentByName(String name);
}
POST Mapping
#PostMapping("/students")
public ResponseEntity<?> addStudent(#RequestBody Student student) {
try {
System.out.println("Student Object is : " + student);
Student studentData = studentRepository.save(student);
if (null == studentData) {
return ResponseEntity.noContent().build();
}
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{name}")
.buildAndExpand(studentData.getName()).toUri();
return new ResponseEntity<>(location, HttpStatus.CREATED);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Post Request JSON
{
"name": "Vinod Kumar",
"class": "8th class",
"subjects": [
{
"name": "Telugu",
"marks": 85
},
{
"name": "English",
"marks": 80
},
{
"name": "Maths",
"marks": 90
}
],
"totalMarks": 580
}
Student Table data
STUDENT_ID STUDENT_CLASS STUDENT_NAME TOTAL_MARKS
1 8th class Vinod Kumar 580
Subject Table data
SUBJECT_ID MARKS SUBJECT_NAME STUDENT_ID
2 85 Telugu null
3 80 English null
4 90 Maths null
Here the issue is the STUDENT_ID column storing null values.
When you save a Student, Hibernate smart enough to insert a Student record to the database, get that record id and save all subjects of the Student with Subject.STUDENT_ID = generated student id, when the student and the subject connected to each other from both sides.
But by some reasons Hibernate doesn't connect a Subject with a Student as Java objects from the Subject side. It doesn't do for you
subject.setStudent(student)
This is the reason why Subject.STUDENT_ID = null in the database.
Before saving a student you have to assign the student to a subject for each subject, doing it in the loop
emptyStreamIfNull(student.getSubjects()).forEach(subject -> setStudent(student));
Some recommendations
Your database schema is not convenient. Student and Subject are tabular data.
So you need an additional object StudentSubjectMark.
Also use Long id for ids (not long id).
You have to log error here
catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}

Get from VIEW in Spring boot

I am beginner with Spring Boot and trying to improve my skills to get new job, so I hope you help me even if the question maybe easy for you as I search a lot and gain nothing.
I need to get by id, but return data is duplicated with only one record, I will show you what I do and the result for more explanation.
In DB side:
I have VW_Prices view in DB and it's data as shown below:
In Spring Boot side:
VW_Prices class is :
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Immutable;
#Entity
#Table(name = "VW_PRICES")
public class VW_Prices implements Serializable {
private long dealId;
private Long quotationId;
private Long productPriceForEjada;
private Long productPriceForClient;
private Long productId;
private Long productQuantity;
private String productName;
#Id
#Column(name = "ID")
public long getDealId() {
return dealId;
}
public void setDealId(long dealId) {
this.dealId = dealId;
}
#Column(name = "PRODUCT_QUANTITY")
public Long getProductQuantity() {
return productQuantity;
}
public void setProductQuantity(Long productQuantity) {
this.productQuantity = productQuantity;
}
#Column(name = "PRODUCT_NAME")
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
#Column(name = "PRODUCT_PRICE_FOR_EJADA")
public Long getProductPriceForEjada() {
return productPriceForEjada;
}
public void setProductPriceForEjada(Long productPriceForEjada) {
this.productPriceForEjada = productPriceForEjada;
}
#Column(name = "PRODUCT_PRICE_FOR_CLIENT")
public Long getProductPriceForClient() {
return productPriceForClient;
}
public void setProductPriceForClient(Long productPriceForClient) {
this.productPriceForClient = productPriceForClient;
}
#Column(name = "PRODUCT_ID")
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
#Column(name = "QUOTATION_ID")
public Long getQuotationId() {
return quotationId;
}
public void setQuotationId(Long quotationId) {
this.quotationId = quotationId;
}
}
and I create VW_PricesRepository
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import springboot.deals_tracker_system.models.VW_Prices;
import springboot.deals_tracker_system.models.VW_Prices_interface;
public interface VW_PricesRepository extends JpaRepository<VW_Prices, Long> {
#Query( nativeQuery = true,value = "SELECT distinct * from VW_Prices v where v.id = :dealID " )
List<VW_Prices> findByDealId( #Param("dealID") Long id);
}
and my in my Service
public List<VW_Prices> findByDealId(Long dealId) {
System.out.println("we are in service");
List<VW_Prices> variableForDebug = VW_pricesRepository.findByDealId(dealId);
for (VW_Prices vw_Prices : variableForDebug) {
System.out.println(vw_Prices.getDealId() + " " + vw_Prices.getProductName());
}
return variableForDebug;
//return VW_pricesRepository.findByDealId(dealId);
}
When I pass dealId = 39 the result comes duplicated and not correct as in below:
how can I get correct data??
The view is made for Quotation Product Table to get product name.
i think the problem is the id annotation you must add GeneratedValue
fro the class:
#Entity
#Table(name = "VW_PRICES")
public class VW_Prices implements Serializable {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private long dealId;
private Long quotationId;
private Long productPriceForEjada;
private Long productPriceForClient;
private Long productId;
private Long productQuantity;
private String productName;
//code..
}
You dont have to use JPQL for this type of queries it's already exist in jpa:
VW_PricesRepository:
public interface VW_PricesRepository extends JpaRepository<VW_Prices, Long> {
}
to get data by id use findById like that:
public VW_Prices findByDealId(Long dealId) {
System.out.println("we are in service");
VW_Prices vw_Prices = VW_pricesRepository.findById(dealId);
System.out.println(vw_Prices.getDealId() + " " +
vw_Prices.getProductName());
}
return vw_Prices;
}
All data should be deleted from VW_Prices table because ids are not unique, try to insert new data with unique id then try the above code
I detect the problem, The view has main table Quotation and I didn't select it's ID and I used ID of the secondary table as the main ID for the View
I just write it if any one Google for such problem

Spring Boot Jpa #ManyToOne : ForeignKey column in DB always populated to null

Employee.Java
`
import lombok.ToString;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#ToString
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int empid;
private String empname;
private String empcontact;
private String empemail;
private String empphoto;
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
private List<Skillset> skillset;
public int getEmpid() {
return empid;
}
public void setEmpid(int empid) {
this.empid = empid;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public String getEmpcontact() {
return empcontact;
}
public void setEmpcontact(String empcontact) {
this.empcontact = empcontact;
}
public String getEmpemail() {
return empemail;
}
public void setEmpemail(String empemail) {
this.empemail = empemail;
}
public String getEmpphoto() {
return empphoto;
}
public void setEmpphoto(String empphoto) {
this.empphoto = empphoto;
}
public List<Skillset> getSkillset() {
return skillset;
}
public void setSkillset(List<Skillset> skillset) {
this.skillset = skillset;
}`
SkillSet.Java
`
package aurozen.assign.aurozenassign.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.ToString;
import javax.persistence.*;
#Entity
public class Skillset {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int skillid;
private String skillname;
#JsonIgnore
#ManyToOne
#JoinColumn(name = "empId", nullable = false,updatable = false, insertable = true)
private Employee employee;
public int getSkillid() {
return skillid;
}
public void setSkillid(int skillid) {
this.skillid = skillid;
}
public String getSkillname() {
return skillname;
}
public void setSkillname(String skillname) {
this.skillname = skillname;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
#Override
public String toString() {
return "Skillset{" +
"skillid='" + skillid + '\'' +
", skillname='" + skillname + '\'' +
", employee=" + employee +
'}';
}
}
`
EmployeeRepositry.java
package aurozen.assign.aurozenassign.repositry;
import aurozen.assign.aurozenassign.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface EmployeeRepositry extends JpaRepository<Employee, Integer> {
Optional<Employee> findByEmpcontact(String s);
}
SkillSetRepositry.java
package aurozen.assign.aurozenassign.repositry;
import aurozen.assign.aurozenassign.entity.Skillset;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SkillsetRepositry extends JpaRepository<Skillset, Integer> {
}
Controller
#PostMapping(value = "/signup",produces = {"application/json"})
public Employee addEmployee(#RequestBody Employee employee) {
empRepo.save(employee);
return employee;
}
Json Data
{
"empname": "sandep",
"empcontact": "9650114890",
"empemail": "aidaih",
"empphoto": "paidpaid",
"skillset": [
{
"skillname": "jop"
}
]
}
I have attached Db Screenshot
Database Screenshot with empid as foreign key in skillset table
foreign key(empid) in the skillset table always populating to null when ever I try to post the data through postman.other fields getting populating without any problem in both the table
The relationship between Skillset and Employee is owned by Skillset. This means JPA will persist the state the Skillset objects have.
But via #RequestBody you are creating an Employee instance.
While that references a Skillset instances, that instance does not reference the Employee.
Therefor no relationship gets persisted.
To fix this add code to setSkillset to set the employee property of it.
Something like this should do:
public void setSkillset(List<Skillset> skillset) {
this.skillset = skillset;
skillset.foreach(s -> s.setEmployee(this));
}

Hibernate didn't create one of tables

I'm learning spring..., I build a simple application.
I have a problem because hibernate does not want to generate one of the models..
I do not know what's wrong
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table(name="access_card")
public class AccessCard implements Serializable{
private static final long serialVersionUID = -4015209774835055079L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private Long id;
#Column(name="key")
private String key;
#Column(name="enabled")
private Boolean enabled;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
#JsonIgnore
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Other classes are written similarly and everything works.
Error:
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "create table access_card (id bigint not null, enabled
bit, key varchar(255), user_id bigint not null, primary key (id))
engine=MyISAM" via JDBC Statement
And properties
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
Follow your comment, The problem pointed out at here
key varchar(255)
The table name is reserved keyword.
See https://hibernate.atlassian.net/browse/HHH-4453
If you still want it, the solution is https://vladmihalcea.com/escape-sql-reserved-keywords-jpa-hibernate/

Resources