AutoIncrement Id PostgreSQL and Spring Boot Data JPA - java

I'm having problems trying to create a new record in my PostgreSQL database. I just want to POST to the REST service a new user (int:id, String:email, String:password) but, I'm having this error:
"exception": "org.springframework.dao.DataIntegrityViolationException",
"message": "could not execute statement; SQL [n/a]; constraint [id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
These are my Java classes:
Domain
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String email;
private String password;
public User() {}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Controller
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserService userService;
#RequestMapping(method = RequestMethod.GET)
public List<User> findAll() {
return userService.findAll();
}
#RequestMapping(method = RequestMethod.POST)
public User addUser(#RequestBody User user) {
userService.addUser(user);
return user;
}
}
Service
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public List<User> findAll() {
return (List<User>) userRepository.findAll();
}
public User addUser(User user) {
userRepository.save(user);
return user;
}
}
Repository
public interface UserRepository extends CrudRepository<User, Integer> {
// TODO
}
SQL
CREATE TABLE users(
id INT PRIMARY KEY NOT NULL,
email TEXT NOT NULL,
password CHAR(20) NOT NULL
);
Please, somebody help me, because I don't know how to tackle this issue.

I found the solution. I need to change the script for these one:
CREATE TABLE users(
id SERIAL PRIMARY KEY NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL
);
Then, the Entity should be annotated with this:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(columnDefinition = "serial")
private Long id;
private String email;
private String password;
public User() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

SQL should be like this..
CREATE TABLE users(
id INT PRIMARY KEY BIGINT NOT NULL AUTO_INCREMENT,
email TEXT NOT NULL,
password CHAR(20) NOT NULL
);

Related

Don't know how to findByRole to return a customised list of users

I am trying to list users in my application based on role. I have an endpoint in my controller which tries to call my userService class .findByRoles method but I dont know how to put the role I want to without having the role as a string(wont work).
adminController.java method:
#GetMapping(path="/users")
public String showUsers( Model model){
var userList = (List<User>) userService.findByRoles("ROLE_TEACHER"); // dont know how to pass a role here
model.addAttribute("userList", userList);
return "users";
}
User.java:
#Entity
#Table(name = "user_table", schema = "public")
public class User {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long user_id;
#Column(name = "name")
private String name;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "confirmed")
private boolean confirmed;
#ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH}, fetch = FetchType.EAGER)
#JoinTable(
name = "user_role_table",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "role_id"))
private Collection<Role> roles = new HashSet<>();
/*******************************************
* Setters and getters
*******************************************/
public Long getId() {
return user_id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setConfirmed(Boolean confirmed) {
this.confirmed = confirmed;
}
public Boolean getConfirmed() {
return confirmed;
}
public void setRoles(Collection roles) {
this.roles = roles;
}
public Collection<Role> getRoles() { return this.roles;
}
}
userRepository:
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
User findByEmail(String email);
User findByRoles(Role role);
}
roleRepository:
public interface RoleRepository extends JpaRepository<Role, Long> {
Role findByName(String name);
}
IUserService.java:
public interface IUserService {
User registerNewUserAccount(UserDto userDto);
List<User> findAll();
Optional<User> findById(Long id);
User findByRoles(Role role);
public void delete(Long id);
public User updateConfirmed(Long id);
}
UserService.java method:
#Override
public User findByRoles(Role role) {
return userRepository.findByRoles(role);
}
Any tips how I can go about to fix this issue?
After tweaking around with the classes I think the most logical method to fix the issue is to use roleRepository method findByName. Furthermore, created findAllByRoles in userRepository, IUserService & UserService for returning a list(check my comment on this answer).
Changed IUserService.java to:
public interface IUserService {
User registerNewUserAccount(UserDto userDto);
List<User> findAll();
Optional<User> findById(Long id);
List<User> findAllByRoles(String roles); //Added this new method (VERY IMPORTANT for returning multiple users)
User findByRoles(String roles);
public void delete(Long id);
public User updateConfirmed(Long id);
}
Changed UserService.java method to:
#Override
public User findByRoles(String roles) {
return userRepository.findByRoles(roleRepository.findByName(roles)); // Using roleRepository here
}
// Added below findAllbyRoles to return a list
#Override
public List<User> findAllByRoles(String roles){
return userRepository.findAllByRoles(roleRepository.findByName(roles));
}
Changed adminController.java method to:
#GetMapping(path="/users")
public String showUsers( Model model){
List<User> userList = userService.findAllByRoles("ROLE_STUDENT");
userList.addAll(userService.findAllByRoles("ROLE_TEACHER"));
model.addAttribute("userList", userList);
return "users";
}

Hibernate can't create a table with #ManyToOne relation

I created a table of "User" which is perfectly created by hibernate, no problem on this one. The problem is on my second model (an entity called "Character") which is a model with a #ManyToOne relation, I don't know why but hibernate can't create this second table.
My server is a MySql instance with AWS RDS. The first table is created by hibernate but not the second.
#Entity
public class Character {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
#ManyToOne
private User joueur;
private String pseudo;
private Integer points;
public Character() {
super();
}
public Character(User joueur) {
// appel a l'autre constructeur
this(joueur, null, null);
}
public Character(User joueur, String pseudo,Integer points) {
super();
this.joueur = joueur;
this.pseudo = pseudo;
this.points = points;
}
public Integer getId() {
return id;
}
public String getPseudo() {
return pseudo;
}
public void setPseudo(String pseudo) {
this.pseudo = pseudo;
}
public Integer getPoints() {
return points;
}
public void setPoints(Integer points) {
this.points = points;
}
public User getJoueur() {
return joueur;
}
}
#Entity // This tells Hibernate to make a table out of this class
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String username;
private String password;
#OneToMany(mappedBy = "joueur")
#OrderBy("id ASC")
private List<Character> personnages;
private String league;
private Integer points;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Character> getPersonnages() {
return personnages;
}
public void setPersonnages(List<Character> personnages) {
this.personnages = personnages;
}
public String getLeague() {
return league;
}
public void setLeague(String league) {
this.league = league;
}
public Integer getPoints() {
return points;
}
public void setPoints(Integer points) {
this.points = points;
}
}
#Controller
#RequestMapping(path="/init")
public class MainController {
#Autowired // This means to get the bean called userRepository
// Which is auto-generated by Spring, we will use it to handle the data
private UserRepository userRepository;
#Autowired
private CharacterRepository characterRepository;
#GetMapping(path="/add") // Map ONLY GET Requests
public String addNewUser () {
User joueur = new User();
joueur.setUsername("testUser");
joueur.setPassword("password");
joueur.setLeague("Bronze");
joueur.setPoints(10000);
userRepository.save(joueur);
Character perso = new Character(joueur,"testPerso1",1000);
characterRepository.save(perso);
return "";
}
#GetMapping(path="/all")
public #ResponseBody Iterable<User> getAllUsers() {
// This returns a JSON or XML with the users
return userRepository.findAll();
}
}
I have this error :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'character add constraint Kdf2yvyvitaqt2u7de3ywfjcv foreign key (joueur_id) refe' at line 1
Ok I found the solution ... JPA annotation fordid the name of the table 'Character", just change the name of the table and it will work perfectly, stupid JPA ...

Why cant i create a foreign key here? ERROR 1215 (HY000): Cannot add foreign key constraint

Im not sure what im doing wrong here i have read the spec but still cant figure it out.I want to add user id as a forign key to my store table but i keep getting error 1215.
My sql code:
CREATE TABLE Store (
id int,
storePersistentId varchar(255),
storename varchar(255),
user_id int,
PRIMARY KEY (id),
FOREIGN KEY (user_id)
REFERENCES user(id)
);
Store.java
#Entity
public class Store {
//every entity requires an id, and we can make it auto generated
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String storePersistentId;
private String storename;
#ManyToOne
public User user;
public Store(User user,String storePersistentId){
}
public Store(){
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStorename() {
return storename;
}
public void setStorename(String storename) {
this.storename = storename;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getStorePersistentId() {
return storePersistentId;
}
public void setStorePersistentId(String storePersistentId) {
this.storePersistentId = storePersistentId;
}
}
User.java
#Entity
public class User {
#Id
#Column
private int id;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
}
}
Any help would be great.
its probally some small mistake but i need another set of eyes to check it out please.
mysql> create table store(id int primary key NOT NULL AUTO_INCREMENT,
username varchar(255),
password varchar(255),
user_id int, foreign key(user_id)
references user(id));
Got it eventually.

My class Controler doesnt see methods from my Service class

Hi everyone i was started to make from scratch my Spring Boot Application. I want to make Booking Application for my portfolio. I am a begginner in coding,past one year I have learning Java. I'm struggling whole day and I don't know where I have problem when I want to call getUser method in my Controller Class? Simply controller class doesn't see
method's is my Service Class.
Class's are in four different packages
com.booking.controller
com.booking.model
com.booking.repository
com.service
Here I have problem, simply it can't see service class.
#Controller
#RequestMapping(path = "/user")
public class UserController{
#Autowired
private UserRepository userRepository;
#GetMapping(path = "/add")
public #ResponseBody String addNewUser(#RequestParam String name,
#RequestParam String username,
#RequestParam String email, #RequestParam String password) {
User n = new User();
n.setName(name);
n.setUsername(username);
n.setEmail(email);
n.setPassword(password);
userRepository.save(n);
return "Saved";
}
#GetMapping(path = "/all")
public #ResponseBody Iterable<User> getAllUsers() {
return userRepository.findAll();
}
#RequestMapping("/{Id}")
public User getUser(#PathVariable Long id) {
return userRepository.getUser(id);
/*Here you can see problem*/
}
}
My User Class
#Entity
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
private String name;
#Column
private String username;
#Column
private String email;
#Column
private String password;
public User() {
}
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 getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
**My Repository Class--
public interface UserRepository extends CrudRepository<User, Long> {
public List<User> findByUsername(String username);
}
My Service Class
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public List<User> getAllUsers(String username) {
List<User> users = new ArrayList<>();
userRepository.findByUsername(username).forEach(users::add);
return users;
}
public User getUser(Long id) {
return userRepository.findOne(id);
}
public void addUser(User user) {
userRepository.save(user);
}
public void updateUser(Long id, User user) {
userRepository.save(user);
}
public void deleteUser(Long id) {
userRepository.delete(id);
}
}

make transient column only when saving entity

I have the next situation. I ahve entity object User:
package models;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import org.hibernate.annotations.Proxy;
#Entity
#Table(name="users")
#Proxy(lazy=true)
public class User {
private int id;
private String login;
private String password;
private String name;
private String email;
private Integer age;
private String country;
private Set<UserRole> roles = new HashSet<UserRole>();
private UserStatus status;
private Date created;
private Date updated;
public User() {
status=UserStatus.A;
}
public User(String user_login, String user_password, String user_name, String user_email) {
this.login = user_login;
this.password = user_password;
this.name = user_name;
this.email = user_email;
status=UserStatus.A;
}
public User(String user_login, String user_password, String user_name, String user_email, int age) {
this(user_login, user_password, user_name, user_email);
this.age = age;
}
public User(String user_login, String user_password, String user_name, String user_email, int age, String country) {
this(user_login, user_password, user_name, user_email, age);
this.country = country;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_id", unique = true)
public int getId() {
return id;
}
public void setId(int user_id) {
this.id = user_id;
}
#Column(name="user_login")
public String getLogin() {
return login;
}
public void setLogin(String user_login) {
this.login = user_login;
}
#Column(name="user_password")
public String getPassword() {
return password;
}
public void setPassword(String user_password) {
this.password = user_password;
}
#Column(name="user_name")
public String getName() {
return name;
}
public void setName(String user_name) {
this.name = user_name;
}
#Column(name="user_email")
public String getEmail() {
return email;
}
public void setEmail(String user_email) {
this.email = user_email;
}
#Column(name="user_age")
public Integer getAge() {
return age;
}
public void setAge(Integer user_age) {
this.age = user_age;
}
#Column(name="user_country")
public String getCountry() {
return country;
}
public void setCountry(String user_country) {
this.country = user_country;
}
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "users_to_userroles", joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "user_role_id ") })
public Set<UserRole> getRoles() {
return roles;
}
public void setRoles(Set<UserRole> user_roles) {
this.roles = user_roles;
}
#Column(name="user_status")
#Enumerated(EnumType.STRING)
public UserStatus getStatus() {
return status;
}
public void setStatus(UserStatus status) {
this.status = status;
}
#Transient
#Column(name="user_created")
public Date getCreated() {
return created;
}
public void setCreated(Date user_created) {
this.created = user_created;
}
#Transient
#Column(name="user_updated")
public Date getUpdated() {
return updated;
}
public void setUpdated(Date user_updated) {
this.updated = user_updated;
}
}
And JSP page (simple form, not related to question) with the form to create new user and table to show all existing users. I have used binding between form and Entity object User (it is inside controller):
User user = new User();
List<User> users = userService.getAllUsers();//to fill table with users
List<UserRole> userRoles = userRolesService.getAllRoles();//to fill tables with users
model.addAttribute("rolesList", userRoles);
model.addAttribute("users", users);
model.put("adminForm", user);//Here adminForm is the name of form in JSP page
Now what is the problem: as you see User has two fields user_created and user_updated (they are created automatically by Postgres server). They are forwarded withh all other fields to table in JSP page. BUT my form in JSP does not provide these fields (no need - right)))), so they are null when transfered from form to controller. And now Hibernate can not add line on Postgres server because two fields are empty((( So my question is:
can I somehow mark these columns as #Transient but only when I save entity not read it from database.
I know I still can bind separate field in form not the whole object. But still is it possible to do what I ask? With existing configuration, new User is saved but these two fields are not read and JSP table columns are empty(((
You need to set the insertable and updatable properties of your column mapping to false. This will make the field read-only for Hibernate.
#Column(name="user_created", insertable=false, updatable=false)

Categories

Resources