Error creating table with Spring Boot and Postgres - spring

I am trying to create an application using Spring and Postgres. Currently I have 3 Entities: User, Role and UserRole.
User
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import javax.persistence.*;
#Data
#Entity
#Builder
#AllArgsConstructor
public class User {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name = "user_id", nullable = false)
private Long id;
#Column(name = "username", nullable = false, unique = true)
private String username;
#Column(name = "password", nullable = false)
private String password;
#Column(name = "name", nullable = false)
private String firstName;
#Column(name = "lastName", nullable = true)
private String lastName;
#Column(name = "gender", nullable = false)
private char gender;
#Column(name = "email", nullable = true)
private String email;
public User() {}
public User(String username, String password, String firstName, String lastName, char gender, String email) {
this.username = username;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.email = email;
}
}
Role
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import javax.persistence.*;
#Data
#Entity
#Builder
#AllArgsConstructor
public class Role {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name = "role_id", nullable = false)
private Long id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "description", nullable = false)
private String description;
public Role () {}
public Role (String name, String description) {
this.name = name;
this.description = description;
}
}
UserRole
import lombok.AllArgsConstructor;
import lombok.Data;
import javax.persistence.*;
#Data
#Entity
#AllArgsConstructor
public class UserRole {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name = "user_role_id")
private Long id;
#OneToOne
#JoinColumn(name = "user_id")
private User user;
#OneToOne
#JoinColumn(name = "role_id")
private Role role;
public UserRole () {}
public UserRole (User user, Role role) {
this.user = user;
this.role = role;
}
}
When running the application, Role and UserRole tables are created in the database correctly, but its not the case with User table. I will appreciate your help :).

user is a reserved keyword in postgresql because of which it is not allowing to create the table with this name. Try with another name.

Related

Spring boot entity has a list of another entity

I have a problem with the following code:
#Entity
#Table(name = "app_user")
#NoArgsConstructor
#AllArgsConstructor
#Data
#Builder
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
private String username;
#Column(unique = true)
private String email;
private String name;
private String password;
#Enumerated(EnumType.STRING)
private Role role;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
#JoinTable(name = "user_shoes",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "shoes_id"))
private List<Shoe> shoes = new ArrayList<>();
#Builder.Default
private final Instant created = new Date().toInstant();
}
#Entity
#Table(name = "shoes")
#NoArgsConstructor
#AllArgsConstructor
#Data
#Builder
public class Shoe {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private User user;
private String brand;
private String type;
private String size;
private String color;
private String image_url;
private String sex;
#Builder.Default
private Instant created = new Date().toInstant();
}
Inside User entity I want to make a list that contains Shoe entities, but I always get an error.
Table 'webshop.shoes' doesn't exist
Anybody know how to fix this problem?
It is required to my home project of a shoe webshop.
Thanks.
I had pretty similar codes with yours.
Please see mine and hope you solve it as I did.
import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
#Entity
#Getter
#Table(name = "orders")
#ToString(exclude = "user")
#NoArgsConstructor(access = AccessLevel.PROTECTED)
#EntityListeners(AuditingEntityListener.class)
#SequenceGenerator(
name = "order_seq_generator"
, sequenceName = "orders_order_id_seq"
, initialValue = 1
, allocationSize = 1
)
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE
, generator = "order_seq_generator")
#Column(name = "order_id")
private Long orderId;
#Column(name = "order_number")
private String orderNumber;
#Column(name = "salad_date")
private LocalDate saladDate;
#Column(name = "order_date")
#CreatedDate
private LocalDateTime orderDate;
#ManyToOne
#JsonBackReference
#JoinColumn(name = "user_id")
private User user;
#Column(name = "cancel_yn", columnDefinition = "boolean default false")
private boolean cancelYn;
#Builder
public Order(String orderNumber, User user, LocalDate saladDate, boolean cancelYn) {
this.orderNumber = orderNumber;
this.user = user;
this.saladDate = saladDate;
this.cancelYn = cancelYn;
}
public void updateOrder(String orderNumber, boolean cancelYn) {
this.orderNumber = orderNumber;
this.cancelYn = cancelYn;
}
}
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
#Entity
#Getter
#ToString
#Table(name = "users")
#NoArgsConstructor(access = AccessLevel.PROTECTED)
#EntityListeners(AuditingEntityListener.class)
#SequenceGenerator(
name= "users_seq_generator"
, sequenceName = "users_user_id_seq"
, initialValue = 1
, allocationSize = 1
)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE
, generator = "users_seq_generator")
#Column(name = "user_id")
private Long userId;
#Column(name = "password")
private String password;
#Column(name = "user_email")
private String userEmail;
#JsonIgnore
#JsonManagedReference // Avoid infinite recursion
#OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST)
private List<Order> orders = new ArrayList<>();
#Column(name = "user_sabun")
private String userSabun;
#Column(name = "user_name")
private String userName;
#Column(name = "user_phone")
private String userPhone;
#Column(name = "send_email_yn")
private boolean sendEmailYn;
#Column(name = "join_date")
#CreatedDate
private LocalDateTime joinDate;
#Builder
public User(Long userId, String userEmail, String password, String userSabun, String userName, String userPhone, boolean sendEmailYn, LocalDateTime joinDate) {
this.userId = userId;
this.userEmail = userEmail;
this.password = password;
this.userSabun = userSabun;
this.userName = userName;
this.userPhone = userPhone;
this.sendEmailYn = sendEmailYn;
this.joinDate = joinDate;
}
public void userUpdate(String userEmail, String userSabun, String userName, String userPhone, boolean sendEmailYn) {
this.userEmail = userEmail;
this.userSabun = userSabun;
this.userName = userName;
this.userPhone = userPhone;
this.sendEmailYn = sendEmailYn;
}
}

(Do not display relationship values)

I have two entity with name of the article and article Category.
and they have one-to-many relationships.
I use #JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class,property = "id")
but I cant see data of article category(category_id) in spring data rest.
ArticleCategory.class
#Entity
#Table(name = "article_category")
#Getter
#Setter
public class ArticleCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "category_name")
private String categoryName;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "articleCategory", fetch = FetchType.LAZY)
private Set<Article> articles = new HashSet<>();
}
Article.class
#Entity
#Table(name = "article")
#Getter
#Setter
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Article implements Serializable {
public Article() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "category_id", nullable = false)
private ArticleCategory articleCategory;
#Column(name = "title")
private String title;
#Column(name = "image_url")
private String image_url;
#Column(name = "short_description")
private String short_description;
#Column(name = "text")
private String text;
#Column(name = "keywords", nullable = true)
private String keywords;
#Column(name = "visit", nullable = false)
private int visit;
#Column(name = "code", nullable = false)
private UUID code;
#Column(name = "date_created")
#CreationTimestamp
private Date dateCreated;
#Column(name = "date_updated", nullable = false)
#UpdateTimestamp
private Date dateUpdated;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
public Article(String title, String image_url, String short_description, String text, String keywords, int visit, UUID code) {
this.title = title;
this.image_url = image_url;
this.short_description = short_description;
this.text = text;
this.keywords = keywords;
this.visit = visit;
this.code = code;
}
}
Article Repository
#CrossOrigin("http://localhost:4200")
#RepositoryRestResource(collectionResourceRel = "article", path = "article")
public interface ArticleRepository extends JpaRepository<Article,Long> {
Article findByCode(UUID uuid);
}
And this is output of spring data rest
enter image description here
That is exactly because you used #JsonManagedReference and #JsonBackReference. Keep in mind the following when using them:
#JsonManagedReference is the forward part of the relationship and is the one that gets serialized normally.
#JsonBackReference is the back part of the relationship and it will be omitted from serialization.
The serialized Article object does not contain a reference to the ArticleCategory object.
If you want to have any ArticleCategory data when serializing Article you can either use #JsonIdentityInfo so that one of the properties is serialized (in this case I've chosen id for both):
#Entity
#Table(name = "article")
#Getter
#Setter
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Article implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "category_id", nullable = false)
private ArticleCategory articleCategory;
}
#Entity
#Table(name = "article_category")
#Getter
#Setter
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ArticleCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "category_name")
private String categoryName;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "articleCategory" ,fetch = FetchType.LAZY)
private Set<Article> articles=new HashSet<>();
}
If you are only interested in categoryId another possibility would be to use #JsonIgnore on private Set<Article> articles property so that it is not serialized:
#Entity
#Table(name = "article_category")
#Getter
#Setter
public class ArticleCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "category_name")
private String categoryName;
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL,mappedBy = "articleCategory" ,fetch = FetchType.LAZY)
private Set<Article> articles=new HashSet<>();
}
If none of those suits your needs you might need to implement your own custom serializer. You can read more about all those options at https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion.
I solved the problem using the controller
And that's why #JsonManageRefrence and #JsonBackRefrence do not work
I replaced the lazy load with the eager load in both entity
#ManyToOne(fetch = FetchType.Eager)
#JoinColumn(name = "user_id")
#JsonManageRefrence
private User user;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "articleCategory",
fetch = FetchType.Eager)
#JsonBackRefrence
private Set<Article> articles = new HashSet<>();
and then add a controller
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
#RequestMapping("/getAllArticle")
public class MyController {
private ArticleRepository articleRepository;
// you must do constructor injection
#GetMapping("/getAllArticle")
public List<Article> allArticle()
{
return articleRepository.findAll();
}
}

OneToOne CascadeType in spring data jpa

I use OneToOne in the spring data JPA and I want to delete a record from the Address table without touching the user. But I can't.
If I remove User, in this case Address is removed, that's good.
But how can you delete an Address without touching the User?
https://github.com/myTestPercon/TestCascade
User.Java
#Entity
#Table(name = "user", schema = "testCascade")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Address address;
// Getter and Setter ...
}
Address.java
#Entity
#Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private User user;
// Getter and Setter ...
}
DeleteController.java
#Controller
public class DeleteController {
#Autowired
ServiceJpa serviceJpa;
#GetMapping(value = "/deleteAddressById")
public String deleteAddressById () {
serviceJpa.deleteAddressById(4L);
return "redirect:/home";
}
}
You got your mapping wrong thats all is the problem .
try the below and see
User.java
#Entity
#Table(name = "user", schema = "testCascade")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="foriegn key column in user table for address example.. address_id")
private Address address;
// Getter and Setter ...
}
Address.java
#Entity
#Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
//name of the address variable in your user class
#OneToOne(mappedBy="address",
cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
private User user;
// Getter and Setter ...
}
In order to solve this problem, you need to read the hibernate Documentation Hibernate Example 162, Example 163, Example 164.
And also I recommend to look at this is Using #PrimaryKeyJoinColumn annotation in spring data jpa
This helped me in solving this problem.
And also you need to specify the parameter orphanRemoval = true
User.java
#Entity(name = "User")
#Table(name = "user", schema = "testother")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Address address;
public void addAddress(Address address) {
address.setUser( this );
this.address = address;
}
public void removeAddress() {
if ( address != null ) {
address.setUser( null );
this.address = null;
}
}
// Getter and Setter
}
Address.java
#Entity(name = "Address")
#Table(name = "address", schema = "testother")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private User user;
// Getter and Setter
}
DeleteController .java
#Controller
public class DeleteController {
#Autowired
ServiceJpa serviceJpa;
#GetMapping(value = "/deleteUser")
public String deleteUser () {
User user = serviceJpa.findUserById(2L).get();
user.removeAddress();
serviceJpa.saveUser(user);
return "/deleteUser";
}
}
Or make a custom SQL query.
#Repository
public interface DeleteAddress extends JpaRepository<Address, Long> {
#Modifying
#Query("delete from Address b where b.id=:id")
void deleteBooks(#Param("id") Long id);
}
public class Address {
#Id
private Long id;
#MapsId
#JoinColumn(name = "id")
private User user;
}
Rename #JoinColumn(name = "id") to #JoinColumn(name = "user_id")
You can't say that the column that will point to user will be the id of the Address

JPA Fetch Types

I have two model classed called users and authorities. I used fetch type EAGER so that all the data even the ones from the authorities tables would be fetched as they are mapped to each other, But for some reason it is not fetching the details from the authorities table.
#Getter
#Setter
#Entity
#Table
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(unique = true)
private String email;
private String firstname;
private String lastname;
private String password;
#OneToMany(mappedBy = "users",
cascade = CascadeType.PERSIST,
fetch = FetchType.EAGER,
targetEntity = Authorities.class)
private Set<Authorities> authorities;
}
#Getter
#Setter
#Entity
#Table
public class Authorities {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String role;
#ManyToOne(targetEntity = Users.class,
cascade = CascadeType.PERSIST,
fetch = FetchType.EAGER)
#JoinColumn(name = "authorities")
private Users users;
}
#Repository
public interface UserRepository extends JpaRepository<Users, Integer> {
Optional<Users> findByEmail(String email);
}
This method findByEmail is not fetching all the details from the database. It is only fetching the data from the users table but not from the authorities table even though i am using fetch type EAGER.
I think that Spring Data ignores fetch types and fetch mode. You can use Entity Graphs. See documentation
#Getter
#Setter
#Entity
#Table
#NamedEntityGraph(name = "authorities.detail", attributeNodes = NamedAttributeNode("authorities"))
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(unique = true)
private String email;
private String firstname;
private String lastname;
private String password;
#OneToMany(mappedBy = "users",
cascade = CascadeType.PERSIST,
fetch = FetchType.EAGER,
targetEntity = Authorities.class)
private Set<Authorities> authorities;
}

How to get an Authenticated User's Details in Spring Security OAuth2

I am unable to extract the current logged in user in Spring Security OAuth2. My goal is to extract the user when the create event on ClientSuggestion entity is triggered and persist it to the database.
Employee.java
#Entity
#Table(name = "er_employee")
public class Employee implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "username", unique = true)
#NotNull
#Size(max = 10)
private String username;
#Column(name = "password_hash")
#NotNull
#Size(min = 8, max = 512)
private String password;
#Column(name = "email_verification_token")
#Size(max = 512)
private String emailVerificationToken;
#Column(name = "password_reset_token")
#Size(max = 512)
private String passwordResetToken;
#Column(name = "active")
#NotNull
private boolean active;
#Column(name = "is_deleted")
#NotNull
private boolean deleted;
#Column(name = "date_of_creation")
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date dateOfCreation;
#OneToMany(mappedBy = "employee")
private List<ClientSuggestion> clientSuggestions;
//Constructors
//Getters ans setters
}
ClientSuggestion.java
#Entity
#Table(name = "er_suggestion")
public class ClientSuggestion implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "content", unique = true)
#NotNull
#Size(max = 200)
private String suggestion;
#ManyToOne
#JoinColumn(name = "employee_id")
private Employee employee;
//Constructors
//Getters ans setters
}
EmployeeRepository.java
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
ClientSuggestionRepository .java
public interface ClientSuggestionRepository extends CrudRepository<ClientSuggestion, Long> {
}
The event handler
#Component
#RepositoryEventHandler(ClientSuggestion.class)
public class ClientSuggestionEventHandler {
Employee employee= (Employee ) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
#HandleBeforeCreate
public void handleClientSuggestionBeforeCreate(ClientSuggestion cs) {
cs.setDeleted(false);
cs.setActive(true);
cs.setPasswordResetToken(Encryptor.generateHash(cs.getPassword, 512));
cs.setEmployee(employee);
}
}
The bean, ClientSuggestionEventHandler, is registered in a configuration class. When I tried running the project, NullPointerException exception is thrown. I wish to find out how to get the current logged employee.
I'm new to Spring Security OAuth2. Thanks.
In Employee.java implement org.springframework.security.core.userdetails.UserDetails class
Employee.java
#Entity
#Table(name = "er_employee")
public class Employee implements Serializable, UserDetails {
And then use Employee employee= (Employee) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

Resources