I'm creating Spring Boot Application with JPA PostgreSQL.
When I compile my spring project, got the following error.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: eveserver.core.entity.User.name in eveserver.core.entity.Role.users
Please, help me to understand what i'm doing wrong.
This is my User.java
package eveserver.core.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "name")
private String username;
#JsonIgnore
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
private boolean enabled = false;
#ManyToMany
#JoinTable(name = "user_role",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles;
public User(){ }
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public User(String username, String password, String email, Set<Role> roles) {
this.username = username;
this.password = password;
this.email = email;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long 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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void enable(){
enabled = true;
}
public void disable(){
enabled = false;
}
}
Role.java
package eveserver.core.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "role")
public class Role implements GrantedAuthority {
#Id
#GeneratedValue
private Long id;
private String name;
#ManyToMany(mappedBy = "role")
#JsonIgnore
private Set<User> users;
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;
}
#Override
public boolean equals(Object obj){
if (obj instanceof Role){
Role r = (Role)obj;
if (r.getId()==this.getId()){
return true;
}
}
return false;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
#Override
public String getAuthority() {
return getName();
}
}
and this is my tables
In your User class, you have a property called roles:
public Set<Role> getRoles() {
return roles;
}
In your Role class, this:
#ManyToMany(mappedBy = "role")
#JsonIgnore
private Set<User> users;
should be:
#ManyToMany(mappedBy = "roles")
#JsonIgnore
private Set<User> users;
mappedBy = "something" is saying, effectively, "within this other entity, there's a property called something that gets a list of entities of this type (the current type that you're in when you use the #ManyToMany annotation). It is not specifying a type or class name like Role.
Related
I am having a problem with my retriveUser method. When I run finbyid method it returns the same repeated values. You can see my repository, user, and userService classes and the result below.
[![findbyid method result][1]][1]
My User Repository Class
package io.javabrains.springsecurity.jpa;
import io.javabrains.*;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import io.javabrains.springsecurity.jpa.models.User;
#Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUserName(String userName);
}
My User Class
#Entity
#Table(name="app_user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy =GenerationType.IDENTITY)
private int id;
private String userName;
private String password;
private boolean active;
private String role;
private String city;
public User(String userName, boolean active, String role, String city) {
super();
this.userName = userName;
this.active = active;
this.role = role;
this.city = city;
}
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "user_cities", joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "city_id", referencedColumnName = "id"))
private Collection<UserCity> usercities = new ArrayList<UserCity>() ;
public Collection<UserCity> getUsercities() {
return usercities;
}
public void setUsercities(Collection<UserCity> usercities) {
this.usercities = usercities;
}
public User() {}
public int getId() {
return id;
}
public void setId(int 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 boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
My Service Class
#RestController
public class HomeResource {
#Autowired
private BCryptPasswordEncoder bcryptPasswordEncoder;
#Autowired
private WeatherService weatherService;
#Autowired
private CityRepository cityRepository;
#Autowired
private UserRepository userRepo;
#GetMapping("/")
public String home() {
return ("<h1>Welcome</h1>");
}
#GetMapping("/user")
public String user() {
return ("Welcome User");
}
#GetMapping("/admin")
public String admin() {
return ("<h1>Welcome Admin</h1>");
}
#GetMapping("/getCities")
public List<UserCity> getCities()
{
return cityRepository.findAll();
}
#GetMapping("/users/{id}")
public ResponseEntity<User> retriveUser(#PathVariable int id){
Optional<User> a=userRepo.findById(id);
return new ResponseEntity<User>(a.get(),HttpStatus.OK);
}
Thanks in advance for your help.
Sincerely
[1]: https://i.stack.imgur.com/gNhO7.png
The repeated value is a nested user from the usercities collection in a User object.
The user (id: 1) has a usercities collection containing one UserCity object (cityName: 'bursa' and users containing the same user (id: 1)). Thus, the user (id: 1) is recursively displayed.
You can add #JsonIgnore annotation to your property (usercities in User or users in UserCity) to cut the recursion.
I am creating an app where there are two entities
users
chatrooms
There is a many to many relationship between users and chatrooms.
I created a many to many relationship with a join table named users_chatrooms. The values are getting populated in the join table correctly when I wrote code for a user to join a chatroom.
My issue is that, I need an endpoint that can fetch all the users of a given chatroom. For this, I need the table created by the join (users_chatrooms) as part of Jpa. How to accomplish this in JPA ?
User class
package com.example.chat.models;
import javax.persistence.*;
import java.util.List;
#Entity
#Table(name="USERS")
public class User {
#Id
#Column(name="userid")
private String username;
#Column(name="pass")
private String password;
#ManyToMany(mappedBy = "users",fetch=FetchType.EAGER,cascade = CascadeType.ALL)
List<Chatroom>rooms;
public List<Chatroom> getRooms() {
return rooms;
}
public void setRooms(List<Chatroom> rooms) {
this.rooms = rooms;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Chatroom class
package com.example.chat.models;
import javax.persistence.*;
import java.util.List;
#Entity
#Table(name="Chatrooms")
public class Chatroom {
#Id
#Column(name="chatroomId")
private String id;
#Column(name="chatRoomName")
private String name;
#Column(name="chatroomDesc")
private String description;
#ManyToMany(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
#JoinTable(
name = "users_chatrooms",
joinColumns = #JoinColumn(name = "chatroomId"),
inverseJoinColumns = #JoinColumn(name = "userid"))
private List<User>users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
You can simply join the two entities using #JoinColumn
#Entity
#Table(name="Chatrooms")
public class Chatroom {
#Id
#Column(name="chatroomId")
private String id;
#Column(name="chatRoomName")
private String name;
#Column(name="chatroomDesc")
private String description;
#ManyToMany(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
#JoinColumn(name = "userid", referencedColumnName = "chatroomId")
private List<User>users;
// getters and setters
}
I want to create a user within the run () method using CommandLineRunner. I want to automatically call this method and register it with JPA as soon as Tomcat runs. Below I share the codes I use within the project.When I ran it this way, the tomcat server worked fine, the system started but was not registered to the database. How do I fix this?
User
#Data
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private int id;
#Column(name = "email")
#Email(message = "*Please provide a valid Email")
#NotEmpty(message = "*Please provide an email")
private String email;
#Column(name = "password")
#Length(min = 5, message = "*Your password must have at least 5 characters")
#NotEmpty(message = "*Please provide your password")
private String password;
#Column(name = "name")
#NotEmpty(message = "*Please provide your name")
private String name;
#Column(name = "last_name")
#NotEmpty(message = "*Please provide your last name")
private String lastName;
#Column(name = "active")
private int active;
//JOIN tables
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
public User() {};
public User(String email, String password, String name, String lastName, int active) {
this.email=email;
this.password=password;
this.name=name;
this.lastName=lastName;
this.active=active;
}
//G&S
public int getId() {
return id;
}
public void setId(int 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;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role
#Data
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private int id;
#Column(name = "role")
private String role;
//G&S
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
UserRepository
#Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
RoleRepository
#Repository("roleRepository")
public interface RoleRepository extends JpaRepository<Role, Integer> {
Role findByRole(String role);
}
Service
public class ServiceImplement implements CommandLineRunner{
#Autowired
UserService userService;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
//$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62 = umut1234
User umut = null;
Role userRole = null;
#Override
public void run(String... args) throws Exception {
umut = new User();
umut.setEmail("umut#umut.com");
umut.setPassword("$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62");
umut.setName("Umut");
umut.setLastName("Eren");
umut.setActive(1);
userRole = roleRepository.findByRole("ADMIN");
umut.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(umut);
System.out.println("***Generated***");
}
}
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
// add these 2 lines and change your impelentation to ApplicationRunner
#Component
#Order(value = 1)
public class ServiceImplement implements ApplicationRunner{
#Autowired
UserService userService;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
//$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62 = umut1234
User umut = null;
Role userRole = null;
#Override
public void run(ApplicationArguments args) throws Exception {
umut = new User();
umut.setEmail("umut#umut.com");
umut.setPassword("$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62");
umut.setName("Umut");
umut.setLastName("Eren");
umut.setActive(1);
//save user before add roles to it
userRepository.save(umut);
userRole = roleRepository.findByRole("ADMIN");
umut.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(umut);
System.out.println("***Generated***");
}
}
public class ServiceImplement implements ApplicationRunner {
#Autowired
UserService userService;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
User umut = null;
Role userRole = null;
#Override
public void run(ApplicationArguments args) throws Exception {
String arguments = String.join(" | ", args.getSourceArgs());
System.out.println(arguments);
if(args.getNonOptionArgs().contains("-register"){
umut = new User();
umut.setEmail("umut#umut.com");
umut.setPassword("$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62");
umut.setName("Umut");
umut.setLastName("Eren");
umut.setActive(1);
userRole = roleRepository.findByRole("ADMIN");
umut.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(umut);
System.out.println("***Generated***");
}
}
}
First time working with Spring Boot and Hibernate.
I'm trying to map my User.java and Role.java classes to a MySQL database in NetBeans. Everything works just fine except for one detail.
When I go to the generated tables using NetBeans' database manager interface in the Services tab and try to manually add a row into user_role table (result of #ManyToMany), it lets me, even with no user or role created yet. I would expect it to prompt me with some error stating that the user id I'm inserting does not exist, for example.
Now, I come from a PostgreSQL/Doctrine background and that's maybe why it's a little odd to me because if I were to do this in pgAdmin well, that's a big no no.
Please, if this is default behavior, tell me how to override it, if not, here is my code with the error somewhere.
User.java
package hello;
import java.util.Set;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Transient;
#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 name;
private String email;
private String username;
private String password;
private String passwordConfirm;
#ManyToMany(targetEntity = Role.class)
#Access(AccessType.FIELD)
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
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;
}
#Transient
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role.java
package hello;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "role")
public class Role {
private Long id;
private String name;
#ManyToMany(targetEntity = User.class, mappedBy = "roles")
#Access(AccessType.FIELD)
private Set<User> users;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
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 Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
If you need more info, please ask.
So If I have a User and a UserRole Table like soo..
User Class
package app.repo.User;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Version
private Long version;
#Column(nullable = false)
private String username;
#Column(nullable = false)
private String password;
#OneToMany(mappedBy = "user")
private Set<UserRole> roles;
protected User() {}
public User(String username, String password) {
this.username = username;
this.password = password;
}
#Override
public String toString() {
return String.format(
"User[id=%d, username='%s', password='%s']",
id, username, password);
}
public long getId() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<UserRole> getRoles() {
return roles;
}
public void setRoles(Set<UserRole> roles) {
this.roles = roles;
}
}
UserRole Class
package app.repo.User;
import javax.persistence.*;
#Entity
#Table(name = "user_roles")
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Version
private Long version;
#Column(name = "role_name")
private String roleName;
#ManyToOne
private User user;
public UserRole() {
}
public UserRole(String roleName, User user) {
this.roleName = roleName;
this.user = user;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public void setUser(User user) {
this.user = user;
}
}
The above example has a oneToMany relationship with UserRole and a ManyToOne Relationship with user.
My first question is... is it possible to save User and UserRole in one save like so...
userDao.save(user);
And second question is. How would I set that up in a JSON post call ? and how would this be done. This is what I am doing now
{
"userId":"1",
"userName":"RestMan",
"password":"happy",
"version":"1",
"email":"restman#gmail.com",
"enabled":"1",
"roles": {
{"user":"1","role_name":"ROLE_COOLGUY"}
}
}
Otherwise I am thinking to just create a Model that saves the two separately in one method
Change the annotation like this : #OneToMany(cascade = CascadeType.ALL)