Error: AnnotationException: mappedBy reference an unknown target entity property - java

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

JPA Repository Findbyid Returns Repeated List

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.

How to access table created by join in JPA

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
}

spring boot mysql jpa Command Line Runner problem

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

Hibernate does not add referential constraint when mapping Java class (Spring Boot app)

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.

Does Spring Save Relationship Data too in Rest Call?

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)

Categories

Resources