org.hibernate.exception.SQLGrammarException when trying to save record - spring-boot

I am new to the world of JPA and hibernate. I have an entity EMPLOYEE for which I am trying to save a simple empty record but I keep on getting the following exception:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause java.sql.SQLSyntaxErrorException: Unknown column 'employee0_.employee_id' in 'field list'
My entity class looks like this:
package com.workforcesoftware.groupmanagementservice.data.entities;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;
#Entity
#Table(name = "employee")
public class Employee implements Serializable {
#Id
#Column(name = "employeeId")
private String employeeId;
#Column(name = "displayEmployeeId")
private String displayEmployeeId;
#Column(name = "accountId")
private String accountId;
#Column(name = "userId")
private String userId;
private String firstName;
private String lastName;
private String displayName;
private String birthDate;
private String phoneNumber;
private String originalHireDate;
private String externalMatchId;
#OneToMany(mappedBy = "employee")
private List<EffectiveDatedEmployee> effectiveDatedEmployees;
#OneToMany(mappedBy = "employee")
private List<Job> jobs;
public Employee(){ }
public Employee(String employeeId, String displayEmployeeId, String accountId, String userId, String firstName,
String lastName, String displayName, String birthDate, String phoneNumber, String originalHireDate,
String externalMatchId, List<EffectiveDatedEmployee> effectiveDatedEmployees, List<Job> jobs) {
this.employeeId = employeeId;
this.displayEmployeeId = displayEmployeeId;
this.accountId = accountId;
this.userId = userId;
this.firstName = firstName;
this.lastName = lastName;
this.displayName = displayName;
this.birthDate = birthDate;
this.phoneNumber = phoneNumber;
this.originalHireDate = originalHireDate;
this.externalMatchId = externalMatchId;
this.effectiveDatedEmployees = effectiveDatedEmployees;
this.jobs = jobs;
}
}
My repository interface looks like:
public interface EmployeeRepository extends JpaRepository<Employee, String> {
}
Finally, my repository calling code looks like this:
Employee employee = new Employee("1", "", "", "", "", "", "", "", "", "", "", null, null);
employeeRepository.save(employee);

Related

Spring boot table to show list of pets by owner id

I'm making a small school project Spring Boot web application. Right now I have made CRUD for Owners table in the database, what I'm trying to do next is when I click button "pets" I want to be able to show only those pets that has the same "owner_id". I guess I should receive "owner_id" from the button that was pressed. How can I make that it works the way it should work? Now when I press button "pets" it shows all list of the pets.
Owner class:
#Entity
#Table(name = "owners")
public class Owner {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#Column(name = "email", nullable = false)
private String email;
#OneToMany(targetEntity = Pet.class,cascade = CascadeType.ALL)
#JoinColumn(name = "owner_id", referencedColumnName = "id")
private List<Pet> pets;
public Owner() {
}
public Owner(String firstName, String lastName, String email) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
}
Pet class:
#Table(name = "pets")
public class Pet {
#Id
private Long id;
private String name;
private String breed;
private int age;
private double weight;
public Pet() {
}
public Pet(String name, String breed, int age, double weight) {
super();
this.name = name;
this.breed = breed;
this.age = age;
this.weight = weight;
}
}
Controller method for list of pets:
#GetMapping("/owner_pets")
public String getAllPetsByOwnerId(Model model) {
model.addAttribute("pets", petService.getAllPetsByOwnerId());
return "owner_pets";
}
Here is the code written so far but it only shows list of all pets
I saw your service method for PerService. I do not see any ownerId being passed to findByOwnerId method. That might be the reason why you are getting all pets in response. What you should ideally do is
package com.veterinary.Veterinary_system.service;
import java.util.List;
import com.veterinary.Veterinary_system.entity.Pet;
public interface PetService {
//Repository declaration
List < Pet > findByOwnerId(Long ownerId){
return petRepository.findByOwnerId(ownerId);
}
Pet savePet(Pet pet);
}

JPA: How can I read particular fields of an Entity?

I use Spring JPA ( Hibernate ) and have bunch of entities which are mapped onto tables.
When I use an entity to write I need many fields in it (see an example below). But when I read, I wanna sometimes read only particular fields like first/last name. How can I perform it using Spring data JPA ? ( because due to CrudRepository nature it returns the whole entity)
#Entity
#Table(name="PERSON")
#AttributeOverride(name = "id", column = #Column(name = "ID_PERSON"))
public class Person extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name="LAST_NAME", length = 100, nullable = false)
private String lastName;
#Column(name="FIRST_NAME", length = 50, nullable = false)
private String firstName;
#Column(name="MIDDLE_NAME", length = 50)
private String middleName;
#Column(name="BIRTHDAY", nullable = false)
#Temporal(value = TemporalType.DATE)
private Date birthday;
#ManyToOne(fetch = FetchType.LAZY, optional = true)
#JoinColumn(name = "ID_SEX")
private Sex sex;
public Person() {
super();
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Sex getSex() {
return sex;
}
public void setSex(Sex sex) {
this.sex = sex;
}
}
There are various possibilities.
With Spring Data JPA you can use projection (that's the name when you only select certain fields/columns of an entity/table).
You can return List of Object[] or a DTO or an Interface.
For example with interface it looks like this:
interface NamesOnly {
String getFirstname();
String getLastname();
}
interface PersonRepository extends Repository<Person, UUID> {
Collection<NamesOnly> findByLastname(String lastname);
}
As you can see the return value most not be of type Person.
Please check out the documentation:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
I was faced with a similar issue and I resorted to this:
Let's say you have your entity FooEntity related to repository FooRepository
To only get certain fields, let's say firstName and lastName using key I had to create a custom query in the FooRepository
In this manner
#Query("select new FooEntity(f.firstName, f.lastName) from FooEntity f where f.key = :key")
Optional<FooEntity> findCustomByKey(#Param("key") BigInteger key);
You also have to ensure that the FooEntity has the constructor accepting the values that you only want to be set or returned in this manner:
public FooEntity(String firstName, String lastName){
// Ensure the constructor is not called with null values
notNull(firstName, "Method called with null parameter (firstName)");
notNull(lastName, "Method called with null parameter (lastName)");
this.firstName = firstName;
this.lastName = lastName;
}
Please the full code below:
public class FooEntity implements Serializable {
#Id
#Column(name = "key")
private BigInteger key;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "birth_date")
private Date birthDate;
#Column(name = "hash")
private String hash;
public FooEntity(String firstName, String lastName){
// Ensure the constructor is not called with null values
notNull(firstName, "Method called with null parameter (firstName)");
notNull(lastName, "Method called with null parameter (lastName)");
this.firstName = firstName;
this.lastName = lastName;
}
// Getters and Setters
}
public interface FooRepository extends JpaRepository<FooEntity, BigInteger>{
#Query("select new FooEntity(f.firstName, f.lastName) from FooEntity f where f.key = :key")
Optional<FooEntity> findCustomById(#Param("key") BigInteger key); // This one only returns two set fields firstName and LastName and the rest as nulls
Optional<FooEntity> findById(BigInteger key) // This one returns all the fields
}

Null Foreign Key (Springboot, Hibernate, Postman)

I am using Springboot with Hibernate and I would like to save a new “post” using a POST request to my database. One thing that I would like to highlight is that I am using the dependency “spring-boot-starter-data-rest”.
Schema of the database (MySQL):
Class User:
#Entity
#Table(name="user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id", nullable = false)
public int id;
#OneToMany(mappedBy = "user_id_fk")
public Set<Post> posts;
#Column(name="email")
private String email;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="create_time")
protected Date createTime;
#Column(name="type")
private String accountType;
public User() {
this.createTime = new java.util.Date();
}
public User(String email, String username, String password, String firstName, String lastName, Date createTime, String accountType) {
this.email = email;
this.username = username;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.createTime = createTime;
this.accountType = accountType;
this.createTime = new java.util.Date();
}
public User(int id, String email, String username, String password, String firstName, String lastName, Date createTime, String accountType) {
this.id = id;
this.email = email;
this.username = username;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.createTime = createTime;
this.accountType = accountType;
this.createTime = new java.util.Date();
}
Plus the Getters & Setters & toString().
Class Post:
#Entity
#Table(name="post")
public class Post implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
public int id;
#ManyToOne(optional = false)
#JoinColumn(name = "user_id_fk", nullable = false)
public User user_id_fk;
#Column(name="comment")
private String comment;
#Column(name="likes")
private int likes;
#Column(name="dislike")
private int dislike;
#Column(name="create_time")
protected Date createTime;
public Post() {
this.createTime = new java.util.Date();
}
public Post(String comment, int likes, int dislike, User user_id_fk) {
this.user_id_fk = user_id_fk;
this.comment = comment;
this.likes = likes;
this.dislike = dislike;
this.createTime = new java.util.Date();
}
public Post(int id, User user_id_fk, String comment, int likes, int dislike) {
this.id = id;
this.user_id_fk = user_id_fk;
this.comment = comment;
this.likes = likes;
this.dislike = dislike;
this.createTime = new java.util.Date();
}
Plus the Getters & Setters & toString().
Post request (I'm using Postman to send the request):
{
"comment" : "This is a comment",
"likes" : 123,
"dislike" : 1,
"user_id_fk" :
[
{
"id" : 1
}
]
}
In the request at the "user_id_fk" I tried with [ {"id" : 1 } ] and with { "id" : 1 } but the result was the same.
Issue:
When I am executing exactly the same code from my controller everything works are excepted. Bear in mind that I am using the dependency “spring-boot-starter-data-rest”.
Also, when I am executing the code without the “optional = false” and “nullable = false” is inserting the data into the database but the “user_id_fk” is null :(.
The error that I am getting:
not-null property references a null or transient value : com.citizen.citizen.entity.Post.user_id_fk;
nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : com.citizen.citizen.entity.Post.user_id_fk]
That means that the foreign key ("user_id_fk") is null but should not be null.
Any help will be greatly appreciated.
I just remove the dependency "spring-boot-starter-data-rest" and I solved the issue by creating my custom rest and everything works. Kisses!
According to this article, you should make user_id_fk nullable and then:
Send POST to create User
Send second POST to create Post
Send PUT to create a relation between the two.
This article states the same.
And the documentation only mentions handling associations via association links.

Hibernate : Unable to locate appropriate constructor on class

i want to retrieve data with DTO Projection using sprind data jpa, but unfortunately when i call the method an error has occurred :
[2020-05-28 21:02:03] Unable to locate appropriate constructor on class [com.burgerbuilder.backend.DTO.Response.UserResponse]. Expected arguments are: java.util.UUID, java.lang.String , java.lang.String , java.lang.String , java.util.Collection
[select new com.burgerbuilder.backend.DTO.Response.UserResponse(u.id,u.email,u.name,u.lastName,u.authorities) from com.burgerbuilder.backend.Model.User u where u.id=:id]
my repository :
#Repository
public interface UserRepository extends JpaRepository<User, UUID> {
#Query("select new com.burgerbuilder.backend.DTO.Response.UserResponse(u.id,u.email,u.name,u.lastName,u.authorities) from User u where u.id=:id")
Optional<UserResponse> findUserById(#Param("id") String id);}
User class:
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Type(type=”uuid-char”)
private UUID id;
#NotNull
private String email;
#NotNull
private String password;
private String name;
private String lastName;
private String phoneNumber;
private String emailVerificationToken;
private boolean isEmailVerified=false;
private boolean isPhoneNumberVerified=false;
#OneToMany(mappedBy = “user”,cascade = CascadeType.ALL)
private List<Authority> authorities=new ArrayList();
DTO Class :
public class UserResponse {
private String userId;
private String email;
private String name;
private String lastName;
private List<Authority> authorities=new ArrayList<>();
public UserResponse(UUID userId, String email, String name, String lastName, List<Authority> authorities) {
this.userId = userId.toString();
this.email = email;
this.name = name;
this.lastName = lastName;
this.authorities=authorities;
}
}
can someone help me please ?

Spring Hibernate lazy load behavior

I am making a web based app in spring/hibernate. In database I am using onetomany and manytoone relations. I have manytoone relationship in users for location and onetomany relationship for users in location. In both entities I have lazy loading option turned on. As per my understanding if this is turned on, the database query to get the location should not be executed until explicitly called for it but whenever I do a get from the userdao the below query is executed which makes me think that even after having the lazy option turned on it is retrieving the location information. Can anyone let me know what am I doing wrong or is this the expected behavior.
Below is my user entity code
package com.kwisque.database.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
#Entity
#Table(name = "USERS")
public class User implements Serializable{
#Id
#Column(name = "USER_ID", unique = true, nullable = false)
private String userId;
#Column(name = "NAME", nullable = true, length = 32)
private String name;
#Column(name = "PASSWORD", nullable = false, length = 64)
private String password;
#Column(name = "EMAIL_ID", nullable = true, length = 128)
private String emailId;
#Column(name = "ACTIVE", nullable = false, length = 1)
private Integer active;
#Column(name = "PROVIDER", nullable = false, length = 32)
private String provider;
#ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
#JoinTable(
name = "USER_ROLE",
joinColumns = #JoinColumn(name = "USER_ID"),
inverseJoinColumns = #JoinColumn(name = "ROLE_ID")
)
private Set<Role> roles = new HashSet<>();
//#ManyToOne(fetch = FetchType.LAZY)
//#JoinColumn(name = "LOCATION_ID", nullable = true)
#ManyToOne(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL})
#JoinTable(name="USER_LOCATION_INFO",
joinColumns={#javax.persistence.JoinColumn(name="USER_ID")},
inverseJoinColumns={#javax.persistence.JoinColumn(name="LOCATION_ID")})
private Location location;
// #OneToMany(fetch = FetchType.LAZY)
// #JoinColumn(name = "SPECIALIZATION_ID", nullable = true)
#OneToMany(fetch=FetchType.LAZY, cascade={javax.persistence.CascadeType.ALL})
#JoinTable(name="USER_SPECIALIZATION_INFO",
joinColumns={#javax.persistence.JoinColumn(name="USER_ID")},
inverseJoinColumns={#javax.persistence.JoinColumn(name="SPECIALIZATION_ID")})
private Set<Specialization> specialization = new HashSet<>();
public User() {
}
public User(final String userId, final String name, final String password, final String emailId, final Integer active, final String provider, final Set<Role> roles, final Location location) {
this.userId = userId;
this.name = name;
this.password = password;
this.emailId = emailId;
this.active = active;
this.provider = provider;
this.roles = roles;
this.location = location;
}
public String getUserId() {
return userId;
}
public void setUserId(final String userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public Integer getActive() {
return active;
}
public void setActive(final Integer active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(final Set<Role> roles) {
this.roles = roles;
}
public String getProvider() {
return provider;
}
public void setProvider(final String provider) {
this.provider = provider;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(final String emailId) {
this.emailId = emailId;
}
public Location getLocation() {
return location;
}
public void setLocation(final Location location) {
this.location = location;
}
}
Location entity code
package com.kwisque.database.model;
import java.io.Serializable;
import java.util.Set;
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.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name = "LOCATION")
public class Location implements Serializable {
private static final long serialVersionUID = -7153748534015057865L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "LOCATION_ID", unique = true, nullable = false)
private Integer locationId;
#Column(name = "ZIP_CODE", nullable = true, length = 132)
private String zipCode;
#Column(name = "STATE_ABBR", nullable = true, length = 132)
private String stateAbbr;
#Column(name = "LATITUDE", nullable = true, length = 132)
private double latitude;
#Column(name = "LONGITUDE", nullable = true, length = 132)
private double longitude;
#Column(name = "CITY", nullable = true, length = 132)
private String city;
#Column(name = "STATE", nullable = true, length = 132)
private String state;
#JsonIgnore
#OneToMany(fetch = FetchType.LAZY, mappedBy = "location")
private Set<User> users;
public double getLatitude() {
return this.latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return this.longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public Location() {
}
public Location(Integer locationId, long longitude, String city, long latitude, String zipCode, String state,
String stateAbbr, Set<User> users) {
this.locationId = locationId;
this.longitude = longitude;
this.latitude = latitude;
this.city = city;
this.state = state;
this.stateAbbr = stateAbbr;
this.users = users;
}
public Integer getLocationId() {
return this.locationId;
}
public void setLocationId(Integer locationId) {
this.locationId = locationId;
}
#JsonIgnore
public Set<User> getUser() {
return this.users;
}
#JsonIgnore
public void setUser(Set<User> users) {
this.users = users;
}
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
public String getZipCode() {
return this.zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getStateAbbr() {
return this.stateAbbr;
}
public void setStateAbbr(String stateAbbr) {
this.stateAbbr = stateAbbr;
}
}
Query being executed at my get from USerDao
Hibernate: select user0_.USER_ID as USER_ID1_3_0_, user0_.ACTIVE as ACTIVE2_3_0_, user0_.EMAIL_ID as EMAIL_ID3_3_0_, user0_.NAME as NAME4_3_0_, user0_.PASSWORD as PASSWORD5_3_0_, user0_.PROVIDER as PROVIDER6_3_0_, user0_1_.LOCATION_ID as LOCATION1_4_0_, roles1_.USER_ID as USER_ID1_3_1_, role2_.ROLE_ID as ROLE_ID2_5_1_, role2_.ROLE_ID as ROLE_ID1_1_2_, role2_.NAME as NAME2_1_2_ from USERS user0_ left outer join USER_LOCATION_INFO user0_1_ on user0_.USER_ID=user0_1_.USER_ID left outer join USER_ROLE roles1_ on user0_.USER_ID=roles1_.USER_ID left outer join ROLE role2_ on roles1_.ROLE_ID=role2_.ROLE_ID where user0_.USER_ID=?

Resources