JPA #OneToMany mapping inserting null values - spring-boot

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);
}

Related

Why am I getting null for the date when I create a Todo entity?

What is wrong with my to-do application? I want the user to be able to add a todo and have it be saved in my MySQL database with the time it was created, but I don't know what I'm doing wrong.
I am new to learning Springboot and would appreciate any suggestions or advice.
Todo Entity:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.util.Date;
#Entity(name = "Todo")
#NoArgsConstructor
#Table(name = "todos")
public class Todo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name="description")
private String description;
#Column(name="target_date")
#CreationTimestamp
private Date targetDate;
public Todo(String description) {
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getTargetDate() {
return targetDate;
}
public void setTargetDate(Date targetDate) {
this.targetDate = targetDate;
}
#Override
public String toString() {
return "Todo{" +
"id=" + id +
", description='" + description + '\'' +
", targetDate=" + targetDate +
'}';
}
}
Adding a Todo with Spring Data JPA
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
import java.util.List;
#Repository
#Component
public interface TodoRepository extends JpaRepository<Todo, Integer> {
#Modifying
#Query(value = "INSERT INTO todos (description) VALUES (:description)", nativeQuery=true)
#Transactional
void addTodo(#Param("description") String description);
}
TodoController
#RestController
#RequestMapping(value = "/api/v1/todos")
#AllArgsConstructor
public class TodoController {
#Autowired
private ITodoService todoService;
#PostMapping(value = "/add-todo")
public String addTodo(#RequestParam String description) {
Todo todo = new Todo();
todo.setDescription(description);
todoService.addTodo(todo);
return todo.toString();
}
after getting a post request, the target_date is getting NULL in MySQL
I assume you can solve it by using persist():
#Autowired EntityManager entityManager;
#PostMapping(value = "/add-todo")
public String addTodo(#RequestParam String description) {
Todo todo = new Todo();
todo.setDescription(description);
entityManager.persist(todo);
return todo.toString();
}

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));
}

Spring Boot Hibernate one to many. Lazy many not written to database

I have two entities. Person (one) and Contactdetails (many).
Contactdetails are lazy loading. I have no problem with creating a new Person and get it written into the database. For my test I use the MySQL database installed locally filled up with dummy data. I run kind of integration test.
In my test code I use #Transactional annotation in order to stay inside one session where I fetch a Person, create a new Contacdetails, connect them together and then save the Person, which will cascade save the Contactdetails too. In theory...
Contactdetails is not written to the database. Interestingly, if I write to console all Contactdetails inside the #Transactional annotated test method, I see the new Contactdetails created. As soon es I leave this test method, this freshly created Contactdetails is no more visible.
My Entities are as follows:
Person:
package com.szivalaszlo.contracts.landon.data.entity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import java.time.LocalDate;
import java.util.Objects;
#Entity
#Table(name="person")
public class Person {
private static Logger logger = LogManager.getLogger();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "date_of_birth")
private LocalDate dateOfBirth;
#Column(name = "first_name_mother")
private String firstNameMother;
#Column(name = "last_name_mother")
private String lastNameMother;
#OneToMany(fetch=FetchType.LAZY, mappedBy = "person", cascade = CascadeType.ALL) // refers to person attribute of Contactdetails class
private List<Contactdetails> contactdetails;
#ManyToMany(fetch=FetchType.LAZY)
#JoinTable(name = "buyer_contract",
joinColumns = #JoinColumn(name = "person_buyerid"),
inverseJoinColumns = #JoinColumn(name = "contractid"))
List<Contract> buyerContracts;
#ManyToMany(fetch=FetchType.LAZY)
#JoinTable(name = "seller_contract",
joinColumns = #JoinColumn(name = "person_sellerid"),
inverseJoinColumns = #JoinColumn(name = "contractid"))
List<Contract> sellerContracts;
public Person(){
}
public Person(String firstName, String lastName, String dateOfBirth, String firstNameMother, String lastNameMother) {
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = LocalDate.parse(dateOfBirth);
this.firstNameMother = firstNameMother;
this.lastNameMother = lastNameMother;
}
public int getId() {
return id;
}
public void setId(int 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 LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getFirstNameMother() {
return firstNameMother;
}
public void setFirstNameMother(String firstNameMother) {
this.firstNameMother = firstNameMother;
}
public String getLastNameMother() {
return lastNameMother;
}
public void setLastNameMother(String lastNameMother) {
this.lastNameMother = lastNameMother;
}
public List<Contactdetails> getContactdetails() {
return contactdetails;
}
public void addContactdetail(Contactdetails contactdetail){
if(null == contactdetails){
contactdetails = new ArrayList<Contactdetails>();
}
contactdetails.add(contactdetail);
}
public String getStringForEqualsCheck(){
return firstName+lastName+dateOfBirth.toString()+firstNameMother+lastNameMother;
}
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof Person))
return false;
if (obj == this)
return true;
return this.getStringForEqualsCheck().equals(((Person) obj).getStringForEqualsCheck());
}
#Override
public int hashCode() {
return Objects.hash(firstName, lastName, dateOfBirth, firstNameMother, lastNameMother);
}
#Override
public String toString() {
return "Person{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", dateOfBirth=" + dateOfBirth +
", firstNameMother='" + firstNameMother + '\'' +
", lastNameMother='" + lastNameMother + '\'' +
'}';
}
}
Contactdetails:
package com.szivalaszlo.contracts.landon.data.entity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.persistence.*;
import java.util.Objects;
#Entity
#Table(name="contactdetails")
public class Contactdetails {
private static Logger logger = LogManager.getLogger();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "address")
private String address;
#Column(name = "email")
private String email;
#Column(name = "phone")
private String phone;
#ManyToOne
#JoinColumn(name = "personid", nullable = false)
private Person person;
public Contactdetails(){
}
public Contactdetails(String address, String email, String phone) {
this.address = address;
this.email = email;
this.phone = phone;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
logger.debug("Person is set for contactdetail: " + this.toString() + " person: " + this.person.toString());
}
public String getStringForEqualsCheck(){
return address+email+phone;
}
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof Contactdetails))
return false;
if (obj == this)
return true;
return this.getStringForEqualsCheck().equals(((Contactdetails) obj).getStringForEqualsCheck());
}
#Override
public int hashCode() {
return Objects.hash(address, email, phone);
}
#Override
public String toString() {
return "Contactdetails{" +
"id=" + id +
", address='" + address + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", person=" + person +
'}';
}
}
Service class:
package com.szivalaszlo.contracts.landon.business.domain;
import com.szivalaszlo.contracts.landon.data.entity.Contactdetails;
import com.szivalaszlo.contracts.landon.data.entity.Person;
import com.szivalaszlo.contracts.landon.data.repository.ContactdetailsRepository;
import com.szivalaszlo.contracts.landon.data.repository.PersonRepository;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
#Service
public class PersonService {
private static Logger logger = LogManager.getLogger();
private PersonRepository personRepository;
private ContactdetailsRepository contactdetailsRepository;
#Autowired
public PersonService(PersonRepository personRepository, ContactdetailsRepository contactdetailsRepository){
this.personRepository = personRepository;
this.contactdetailsRepository = contactdetailsRepository;
}
public int createPerson(String firstName, String lastName, String dateOfBirth, String firstNameMother, String lastNameMother){
Person person = new Person(firstName, lastName, dateOfBirth, firstNameMother, lastNameMother);
if(personAlreadyExistsInDb(person)){
logger.debug("Same person already found in Db. Person: " + person.toString());
return -1;
}else{
personRepository.save(person);
return person.getId();
}
}
private boolean personAlreadyExistsInDb(Person person){
HashSet<Person> allPersonFromDb = personRepository.findAll();
if (allPersonFromDb.contains(person)){
return true;
}else{
return false;
}
}
public void createContactdetailsForPerson(Person person, String address, String email, String phone){
Contactdetails contactdetails = new Contactdetails(address, email, phone);
if(contactdetailsAlreadyExistForPerson(contactdetails, person)){
logger.debug("Same contactdetail for person already found " + person.toString() + " " + contactdetails.toString());
} else{
contactdetails.setPerson(person);
person.addContactdetail(contactdetails);
contactdetailsRepository.save(contactdetails);
personRepository.save(person);
}
}
private boolean contactdetailsAlreadyExistForPerson(Contactdetails contactdetails, Person person){
List<Contactdetails> allContactdetailsForPersonFromDb = person.getContactdetails();
if(null == allContactdetailsForPersonFromDb || allContactdetailsForPersonFromDb.size() == 0){
return false;
}
if(!allContactdetailsForPersonFromDb.contains(contactdetails)){
return false;
}
return true;
}
}
Test class:
package com.szivalaszlo.contracts;
import com.szivalaszlo.contracts.landon.business.domain.PersonService;
import com.szivalaszlo.contracts.landon.data.entity.Contactdetails;
import com.szivalaszlo.contracts.landon.data.entity.Person;
import com.szivalaszlo.contracts.landon.data.repository.ContactdetailsRepository;
import com.szivalaszlo.contracts.landon.data.repository.PersonRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Random;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PersonServiceTest_ {
private static Logger logger = LogManager.getLogger();
#Autowired
private PersonRepository personRepository;
#Autowired
private ContactdetailsRepository contactdetailsRepository;
Random rand = new Random();
int randomNumber = rand.nextInt(899)+100;
private String address = "test address street 1 in City "+randomNumber;
private String email = "testemail#exmaple.com " +randomNumber;
private String phone = "+41 12 345 78 90 " +randomNumber;
#Test
#Transactional(propagation = Propagation.REQUIRED)
public void it_should_save_contactdetail_to_person(){
PersonService testPersonService = new PersonService(personRepository, contactdetailsRepository);
Person testPerson = personRepository.findById(179); //I have an id# 179 Person in the database fully detailed.
testPersonService.createContactdetailsForPerson(testPerson, address, email, phone);
List<Contactdetails> allStoredContactdetailsinDB = contactdetailsRepository.findAll();
allStoredContactdetailsinDB.forEach(item->System.out.println(item));
}
}
The test runs with no error. I see the following output in the console:
Bradlystad, ND 98886-5789', email='maverick85#example.com', phone='464-812-3618', person=Person{id=98, firstName='Eldridge', lastName='Reichel', dateOfBirth=1981-08-07, firstNameMother='Brianne', lastNameMother='Ryan'}}
Contactdetails{id=99, address='569 Langosh Turnpike Suite 235
East Archibald, FL 43208-3081', email='spouros#example.org', phone='08976297815', person=Person{id=99, firstName='Myrtie', lastName='Graham', dateOfBirth=1982-01-19, firstNameMother='Libby', lastNameMother='Veum'}}
Contactdetails{id=100, address='010 Pfeffer Islands
Kiehnside, FL 25044-1157', email='paucek.grover#example.com', phone='1-157-850-0688x390', person=Person{id=100, firstName='Katheryn', lastName='Hoppe', dateOfBirth=2009-06-22, firstNameMother='Virginie', lastNameMother='Donnelly'}}
Contactdetails{id=106, address='test address street 1 in City 623', email='testemail#exmaple.com 623', phone='+41 12 345 78 90 623', person=Person{id=179, firstName='TestJhonFirst808', lastName='TestSmithLast808', dateOfBirth=1990-11-11, firstNameMother='TestJackieMotherFirst808', lastNameMother='TestSmithMotherLast808'}}
The interesting part is the last line which shows, that the Contactdetails is created in the db with id#106.
When I query the database after the test is run, I don't see the new line in the table.
By default, test transactions will be automatically rolled back after
completion of the test; however, transactional commit and rollback
behavior can be configured declaratively via the #Commit and #Rollback
annotations
Add the following annotation to your test:
#Rollback(false)

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'demo-db.common_bean' doesn't exist

I am trying to create Spring boot application with JPARepository.My aim is to create the application generic.
In my application i have 4 common functionalities for all the entities as follows :
getAll
getAllNewAfterLastSyncDate
getAllModifiedAfterLastSyncDate
getAllDeletedAfterLastSyncDate
To achive this and avoid redundency of code i created one generic base repository which extends JPARepository as follows :
BaseRepository.java
package dev.ashish.syncdemo.utlities;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
#NoRepositoryBean
public interface BaseRepository<T> extends JpaRepository<T, Long>{
**#Query("select t from #{#entityName} t where t.deleteFlag = 'F' ")**
public List<T> getAll();
/*public List<T> getAllNewAfterLastSyncDate();
public List<T> getAllModifiedAfterLastSyncDate();
public List<T> getAllDeletedAfterLastSyncDate();
*/
}
I have created common bean which will be extended by all entities in my aplication as it has 5 common attributes or fields used for all entities.
CommonBean.java
package dev.ashish.syncdemo.beans;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class CommonBean {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private Long id;
#Column(name = "code")
private String code;
#Column(name = "created_by")
private Long createdBy;
#Column(name = "created_oy")
private Timestamp createdOn;
#Column(name = "modified_by")
private Long modifiedBy;
#Column(name = "modified_on")
private Timestamp modifiedOn;
#Column(name = "delete_flag")
private String deleteFlag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public Timestamp getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Timestamp createdOn) {
this.createdOn = createdOn;
}
public Long getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(Long modifiedBy) {
this.modifiedBy = modifiedBy;
}
public Timestamp getModifiedOn() {
return modifiedOn;
}
public void setModifiedOn(Timestamp modifiedOn) {
this.modifiedOn = modifiedOn;
}
public String getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(String deleteFlag) {
this.deleteFlag = deleteFlag;
}
}
Now Consider i want to use this for customer entity
CustomerEntity.java
package dev.ashish.syncdemo.beans;
import javax.persistence.Column;
public class CustomerEntity extends CommonBean{
#Column(name="first_name")
private String firstName;
#Column(name="middle_name")
private String middleName;
#Column(name="last_name")
private String lastName;
#Column(name="address1")
private String address1;
#Column(name="address2")
private String address2;
#Column(name="landline_no")
private String landlineNo;
#Column(name="mobile_no")
private String mobileNo;
#Column(name="email_id")
private String emailId;
#Column(name="city")
private String city;
#Column(name="state")
private String state;
#Column(name="country")
private String country;
#Column(name="pin_code")
private String pinCode;
#Column(name="fax_number")
private String faxNumber;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress1() {
return address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getLandlineNo() {
return landlineNo;
}
public void setLandlineNo(String landlineNo) {
this.landlineNo = landlineNo;
}
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
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 getPinCode() {
return pinCode;
}
public void setPinCode(String pinCode) {
this.pinCode = pinCode;
}
public String getFaxNumber() {
return faxNumber;
}
public void setFaxNumber(String faxNumber) {
this.faxNumber = faxNumber;
}
#Override
public String toString() {
return "CustomerEntity [firstName=" + firstName + ", middleName=" + middleName + ", lastName=" + lastName
+ ", address1=" + address1 + ", address2=" + address2 + ", landlineNo=" + landlineNo + ", mobileNo="
+ mobileNo + ", emailId=" + emailId + ", city=" + city + ", state=" + state + ", country=" + country
+ ", pinCode=" + pinCode + ", faxNumber=" + faxNumber + ", getId()=" + getId() + ", getCode()="
+ getCode() + ", getCreatedBy()=" + getCreatedBy() + ", getCreatedOn()=" + getCreatedOn()
+ ", getModifiedBy()=" + getModifiedBy() + ", getModifiedOn()=" + getModifiedOn() + ", getDeleteFlag()="
+ getDeleteFlag() + "]";
}
}
I created CustomerService which extends BaseRepositoy as follows:
CustomerService.java
package dev.ashish.syncdemo.service;
import org.springframework.stereotype.Service;
import dev.ashish.syncdemo.beans.CustomerEntity;
import dev.ashish.syncdemo.utlities.BaseRepository;
#Service("customerService")
public interface CustomerService extends BaseRepository<CustomerEntity>{
}
FrontController.java
package dev.ashish.syncdemo.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import dev.ashish.syncdemo.service.CustomerService;
import dev.ashish.syncdemo.utlities.Constants;
#RestController
#RequestMapping("/frontgate")
public class FrontController {
#Autowired
private CustomerService customerService;
#RequestMapping(value = "/getres", method = RequestMethod.POST)
public String getRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
String reqStr = request.getReader().readLine();
System.out.println("Request is : " + reqStr);
Map<String, Object> reqMap = new Gson().fromJson(reqStr, new TypeToken<HashMap<String, Object>>() {
}.getType());
System.out.println("Req Map " + reqMap);
return parseRequest(reqMap);
}
public String parseRequest(Map<String, Object> reqMap)
{
String entity = (String)reqMap.get(Constants.ENTITY);
String action = (String)reqMap.get(Constants.ACTION);
String pageSize = (String)reqMap.get(Constants.PAGE_SIZE);
String pageNumber = (String)reqMap.get(Constants.PAGE_NUMBER);
String lastSyncDate = (String)reqMap.get(Constants.LAST_SYNC_DATE);
return customerService.getAll().toString();
}
}
SyncDemoApplication.java
package dev.ashish;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SyncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SyncDemoApplication.class, args);
}
}
Application flow is as follows:
Request will come to FrontController then it will be forwarded to customerservice which is extending base repository of type JPArepository.
As there are all common functionalities i dont want to create repository for all entities separately and write query for each of them. As you can see i am using SPEL #{#entityName} passing entity name at runtime to query in #Query annotation.
When i try to run application it gives me following exception :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'demo-db.common_bean' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.7.0_67]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.7.0_67]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.7.0_67]
at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:1.7.0_67]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) ~[mysql-connector-java-5.1.35.jar:5.1.35]
Query being fired is as follows :
Hibernate: select customeren0_.id as id2_0_, customeren0_.code as code3_0_, customeren0_.created_by as created_4_0_, customeren0_.created_oy as created_5_0_, customeren0_.delete_flag as delete_f6_0_, customeren0_.modified_by as modified7_0_, customeren0_.modified_on as modified8_0_, customeren0_.address1 as address9_0_, customeren0_.address2 as address10_0_, customeren0_.city as city11_0_, customeren0_.country as country12_0_, customeren0_.email_id as email_i13_0_, customeren0_.fax_number as fax_num14_0_, customeren0_.first_name as first_n15_0_, customeren0_.landline_no as landlin16_0_, customeren0_.last_name as last_na17_0_, customeren0_.middle_name as middle_18_0_, customeren0_.mobile_no as mobile_19_0_, customeren0_.pin_code as pin_cod20_0_, customeren0_.state as state21_0_
from **common_bean** customeren0_ where customeren0_.dtype='CustomerEntity' and customeren0_.delete_flag='F'
Instead of common_bean in from clause it should be customer as i am doing operation for entity customer.
Please let me know what i am doing wrong.

Resources