I am trying to do a many-to-many relationship between my tables using java, but I ran into a problem. The way I designed it so far is User <-> Roles <-> Privileges and all of the tables and columns are recognised except for the last "referencedColumnName = "privilege_id" in Role.java which is not recognised and my IDE does not give any suggestions for this field.
I am not sure if this is the main problem for my project but I do encounter a throwLazyInitializationException when a user tries to login.
User.java
package com.lukas.ramonas.cms.Model;
import javax.persistence.*;
import java.util.Collection;
import java.util.List;
/*******************************************
* Defined user model
*******************************************/
#Entity
#Table(name = "user_table", schema = "public")
public class User {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int user_id;
private String name;
private String username;
private String password;
private String email;
private boolean confirmed;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#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;
/*******************************************
* Setters and getters
*******************************************/
public Integer 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;
}
}
Roles.java
package com.lukas.ramonas.cms.Model;
import javax.persistence.*;
import java.util.Collection;
/*******************************************
* Defined role model
*******************************************/
#Entity
#Table(name = "role_table", schema = "public")
public class Role {
#Id
#Column(name = "role_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int role_id;
private String name;
#ManyToMany(mappedBy = "roles")
private Collection<User> users;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(
name = "role_privilege_table",
joinColumns = #JoinColumn(name = "role_id", referencedColumnName = "role_id"),
inverseJoinColumns = #JoinColumn(name = "privilege_id", referencedColumnName = "privilege_id"))
private Collection<Privilege> privileges;
public String getName() {
return this.name;
}
public Collection<Privilege> getPrivileges() {
return this.privileges;
}
}
Privilege.java
package com.lukas.ramonas.cms.Model;
import javax.persistence.*;
import java.util.Collection;
/*******************************************
* Defined privilege model
*******************************************/
#Entity
public class Privilege {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int privilege_id;
private String name;
#ManyToMany(mappedBy = "privileges")
private Collection<Role> roles;
public String getName() {
return this.name;
}
}
Any suggestion is greatly appreciated and if you need any extra info I would be happy to provide.
So the fix to this was really simple.
In my privilege.java class I forgot to add the #Table annotation.
I could fix the problem by adding #Table(name = "privilege_table", schema = "public") to my class as such :
package com.lukas.ramonas.cms.Model;
import javax.persistence.*;
import java.util.Collection;
/*******************************************
* Defined privilege model
*******************************************/
#Entity
#Table(name = "privilege_table", schema = "public")
public class Privilege {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int privilege_id;
private String name;
#ManyToMany(mappedBy = "privileges")
private Collection<Role> roles;
public String getName() {
return this.name;
}
}
Related
This question already has answers here:
Hibernate and JSON - is there a definitive solution to circular dependencies?
(4 answers)
Closed 3 months ago.
I have two Entities(Group and User) which have some one to many and many to many relations and I have marked these as fetch type lazy, but while retrieving just a single Group entity I am getting all the entities which are present in the Group class which is leading to StackOverflow error.
Group.java
package com.bezkoder.springjwt.models;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Entity
#Table(name = "grp")
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String groupName;
#Column
private String createdBy;
public Group(String groupName, String createdBy ) {
this.groupName = groupName;
this.createdBy = createdBy;
}
public Group() {
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "user_group",
joinColumns = #JoinColumn(name = "user_id",referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "group_id",referencedColumnName = "id")
)
private Set<User> users = new HashSet<>();
#OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
,fetch = FetchType.LAZY,mappedBy="group")
private List<Post> postList = new ArrayList<>();
public List<Post> getPostList() {
return postList;
}
public void setPostList(List<Post> postList) {
this.postList = postList;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void setId(Long id) {
this.id = id;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public Long getId() {
return id;
}
}
User.java
package com.bezkoder.springjwt.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
#Entity
#Table(name = "users",
uniqueConstraints = {
#UniqueConstraint(columnNames = "username"),
#UniqueConstraint(columnNames = "email")
})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable( name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
#ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
},
mappedBy = "users")
#JsonIgnore
private Set<Group> groups = new HashSet<>();
public Set<Group> getGroups() {
return groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
#NotBlank
#Size(max = 20)
private String username;
#NotBlank
#Size(max = 50)
#Email
private String email;
#NotBlank
#Size(max = 120)
private String password;
public User() {
}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
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 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 Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Error
java.lang.StackOverflowError: null
at java.base/jdk.internal.misc.Unsafe.allocateUninitializedArray(Unsafe.java:1380) ~[na:na]
at java.base/java.lang.StringConcatHelper.newArray(StringConcatHelper.java:494) ~[na:na]
at java.base/java.lang.StringConcatHelper.simpleConcat(StringConcatHelper.java:421) ~[na:na]
at java.base/java.lang.String.concat(String.java:2768) ~[na:na]
at java.base/java.net.URLStreamHandler.parseURL(URLStreamHandler.java:265) ~[na:na]
at java.base/sun.net.www.protocol.file.Handler.parseURL(Handler.java:67) ~[na:na]
at java.base/java.net.URL.<init>(URL.java:703) ~[na:na]
at java.base/java.net.URL.<init>(URL.java:569) ~[na:na]
at java.base/jdk.internal.loader.URLClassPath$FileLoader.getResource(URLClassPath.java:1246) ~[na:na]
at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:322) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:757) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at com.fasterxml.jackson.databind.JsonMappingException.prependPath(JsonMappingException.java:445) ~[jackson-databind-2.13.3.jar:2.13.3]
Controller class debug(Group has infinite users and as users has groups there is some recursion happening)
What you are seeing is no indication that eager loading is happening.
#Jhilton is close, although it is not the ResponseEntity that loads all the references, it is your debugger in the screenshot and Jackson in the stack trace.
Lazy loading is build to transparently load entities when needed and this is exactly what is happening when you try to display an entity in the debugger.
And it is also what happens when a serializer tries to navigate the object graph.
The link given by Jhilten in the comments should help you solve the problem.
Note that there isn't an infinite number of users or groups, it is the same user and the same group over and over again.
In my app users can add movies to their watchlist. The movie data comes from an external API. Each movie has its own unique id. For example: Star Wars - A new hope has id 11. And Fight Club has id 550.
When a user adds a movie I pass the whole movie object from the front-end to the back-end:
Component:
createMovie(movie: Movie): void {
this._dataService.createMovie<Movie>({'name': 'Star Wars - A new hope', 'id': 11})
.subscribe((data) => this.movies.push(data),
error => () => {
'something went wrong';
},
() => {
// console.log(this.movies);
});
}
In this case I'm using example data.
Service:
public createMovie<T>(movie: Movie): Observable<T> {
return this.http.post<T>('/api/movies/', movie, {headers: this.getToken()});
}
The MovieController in the back-end:
#RequestMapping(value = "/", method = RequestMethod.POST)
public Movie createMovie(#RequestBody Movie movie){
return movieService.createMovie(movie);
}
The MovieService:
#Override
public Movie createMovie(Movie movie) {
User current_user = userService.getUser();
current_user.addMovie(movie);
userRepository.save(current_user);
return movie;
}
And the User model:
public void addMovie(Movie movie) {
movies.add(movie);
movie.getUsers().add(this);
}
When the movie is saved in the database it's saved with a unique id, starting from 1. How would I map the id from the front-end to the id of the object in my database? I could create another column "external_id" and map it to that, but I think that's a lesser solution than to use the id from the external API.
//edit. Added my movie and user model:
package com.movieseat.models;
import com.movieseat.model.security.User;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity(name = "Movie")
#Table(name = "movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Integer id;
private String name;
private String description;
#ManyToMany(mappedBy = "movies")
private Set<User> users = new HashSet<>();
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
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 getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
User model:
package com.movieseat.model.security;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.movieseat.models.Movie;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Entity(name = "User")
#Table(name = "USER")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class User {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
#SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 1)
private Long id;
#Column(name = "USERNAME", length = 50, unique = true)
#NotNull
#Size(min = 4, max = 50)
private String username;
#Column(name = "PASSWORD", length = 100)
#NotNull
#Size(min = 4, max = 100)
private String password;
#Column(name = "FIRSTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String firstname;
#Column(name = "LASTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String lastname;
#Column(name = "EMAIL", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String email;
#Column(name = "ENABLED")
#NotNull
private Boolean enabled;
#Column(name = "LASTPASSWORDRESETDATE")
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date lastPasswordResetDate;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "USER_AUTHORITY",
joinColumns = {#JoinColumn(name = "USER_ID", referencedColumnName = "ID")},
inverseJoinColumns = {#JoinColumn(name = "AUTHORITY_ID", referencedColumnName = "ID")})
private List<Authority> authorities;
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 getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public Date getLastPasswordResetDate() {
return lastPasswordResetDate;
}
public void setLastPasswordResetDate(Date lastPasswordResetDate) {
this.lastPasswordResetDate = lastPasswordResetDate;
}
#ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "user_movie",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies = new HashSet<>();
public void addMovie(Movie movie) {
movies.add(movie);
movie.getUsers().add(this);
}
public void removeMovie(Movie movie) {
movies.remove(movie);
movie.getUsers().remove(this);
}
}
I have a user and a movie model:
user:
#Entity(name = "User")
#Table(name = "USER")
public class User {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
#SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 1)
private Long id;
#Column(name = "USERNAME", length = 50, unique = true)
#NotNull
#Size(min = 4, max = 50)
private String username;
#Column(name = "PASSWORD", length = 100)
#NotNull
#Size(min = 4, max = 100)
private String password;
#Column(name = "FIRSTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String firstname;
#Column(name = "LASTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String lastname;
#Column(name = "EMAIL", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String email;
#Column(name = "ENABLED")
#NotNull
private Boolean enabled;
#Column(name = "LASTPASSWORDRESETDATE")
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date lastPasswordResetDate;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "USER_AUTHORITY",
joinColumns = {#JoinColumn(name = "USER_ID", referencedColumnName = "ID")},
inverseJoinColumns = {#JoinColumn(name = "AUTHORITY_ID", referencedColumnName = "ID")})
private List<Authority> authorities;
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 getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public Date getLastPasswordResetDate() {
return lastPasswordResetDate;
}
public void setLastPasswordResetDate(Date lastPasswordResetDate) {
this.lastPasswordResetDate = lastPasswordResetDate;
}
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "user_movie",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies;
public Set<Movie> getMovies() {
return movies;
}
public void setMovies(Set<Movie> movies) {
this.movies = movies;
}
}
movie:
#Entity(name = "Movie")
#Table(name = "movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
public Movie(){}
public Movie(Integer id, String name ) {
this.id = id;
this.name = name;
}
#ManyToMany(mappedBy = "movies")
private Set<User> users;
public Set<User> getUsers() {
return users;
}
public void addUser(User user){
System.out.println("ADD MOVIE: " + user);
users.add(user);
user.getMovies().add(this);
}
public void setUsers(Set<User> users) {
this.users = users;
}
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;
}
#Override
public String toString(){
return "id: " + id + "name: " + name;
}
}
I've set up a many to many relation between these models. With, if I am correct, the user as the owner of the relation.
In my MovieController.java I have:
#RequestMapping(value = "/", method = RequestMethod.POST)
public Movie createMovie(#RequestBody Movie movie){
return movieService.createMovie(movie);
}
This calls the MovieService.java:
#Override
public Movie createMovie(Movie movie) {
return movieRepository.save(movie);
}
And this calls the MovieRepository.java:
#Repository
public interface MovieRepository extends CrudRepository<Movie, Serializable> {}
When I call the post methode from my front-end a movie record is saved in my movie table, but no record is created in the user_movie table. Doesn't Hibernate do this implicit since I set up a Many to Many relation between user and movie?
For the first view, your code is correct.
The problem can be in GenerationType.SEQUENCE (try to use GenerationType.AUTO for User's id), or you need to add #Transactional to your controller.
You save the movie and in order to also have the user saved the cascade has to be set in the movie. Otherwise you can keep the cascade in user and save him.
You need to put the cascade to the entity on which you call save to cascade it.
Movie{
#ManyToMany(mappedBy = "movies", cascade={CascadeType.ALL})
private Set<User> users;
public Set<User> getUsers() {
return users;
}
}
User {
#ManyToMany
#JoinTable(name = "user_movie",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies;
}
Don't forget to add the user to movie and vice versa before saving.
As with all bi-directional relationships it is your object model's and application's responsibility to maintain the relationship in both direction. There is no magic in JPA, if you add or remove to one side of the collection, you must also add or remove from the other side, see object corruption. Technically the database will be updated correctly if you only add/remove from the owning side of the relationship, but then your object model will be out of synch, which can cause issues.
see here: https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
I have following entity classes:
#MappedSuperclass
public class AbstractEntity implements Serializable, Comparable<AbstractEntity> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
protected Integer id;
#Override
public int compareTo(AbstractEntity o) {
return this.toString().compareTo(o.toString());
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
#Entity
#Table(name = "ticket")
#NamedQueries({
#NamedQuery(name = "Ticket.findAll", query = "SELECT t FROM Ticket t")})
public class Ticket extends AbstractEntity {
#Column(name = "title")
private String title;
#Column(name = "description")
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private TicketStatus status;
#Enumerated(EnumType.STRING)
#Column(name = "priority")
private TicketPriority priority;
#Column(name = "categories")
private String categories;
#Column(name = "views")
private Integer views;
#Column(name = "date_time_created")
#Temporal(TemporalType.TIMESTAMP)
private Date dateTimeCreated;
#Column(name = "date_time_modified")
#Temporal(TemporalType.TIMESTAMP)
private Date dateTimeModified;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "ticketId")
private List<TicketFollower> ticketFollowerList;
#JoinColumn(name = "project_id", referencedColumnName = "id")
#ManyToOne(optional = false)
private Project projectId;
#JoinColumn(name = "ticket_attachment_id", referencedColumnName = "id")
#ManyToOne
private TicketAttachment ticketAttachmentId;
#JoinColumn(name = "user_id", referencedColumnName = "id")
#ManyToOne(optional = false)
private User userId;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "ticketId")
private List<TicketComment> ticketCommentList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "ticketId")
private List<TicketAttachment> ticketAttachmentList;
#Inject
public Ticket() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
...
#Override
public String toString() {
return getTitle();
}
}
#Entity
#Table(name = "user")
#NamedQueries({
#NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")})
public class User extends AbstractEntity {
#Enumerated(EnumType.STRING)
#Column(name = "role")
private Role role;
#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 = "email")
private String email;
#Column(name = "avatar_path")
private String avatarPath;
#Column(name = "date_time_registered")
#Temporal(TemporalType.TIMESTAMP)
private Date dateTimeRegistered;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<TicketFollower> ticketFollowerList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<Ticket> ticketList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<TicketComment> ticketCommentList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<ProjectFollower> projectFollowerList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<TicketAttachment> ticketAttachmentList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
private List<Project> projectList;
#Inject
public User() {}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
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 getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
I get this exception from creating a hibernate Criteria. In my TicketDao class I have a method which search ticket by username, and when I invoke code below
Criteria criteria = session.createCriteria(Ticket.class);
criteria.add(Restrictions.eq("userId.username", username));
it throws exception:
could not resolve property: userId.username of: com.entities.Ticket
However, when I write criteria like:
criteria.add(Restrictions.eq("userId.id", userId));
it does not show any exception and returns me result. Any idea why my syntax for criteria.add(Restrictions.eq("userId.username", username)); and other properties like firstname, last name is wrong ?
Criteria does not work like EL or Java methods or attributes, you cannot refer to inner objects with a dot ..
You have to create a restriction in Ticket, right? What does Ticket has? An User. Then... you have to create a new User, set the username to this User and then set the created User to Ticket's criteria:
Criteria criteria = session.createCriteria(Ticket.class);
User user = new User();
user.setUsername(username);
criteria.add(Restrictions.eq("user", user));
This is most likely a very basic question, but nevertheless:
Basically the User entity has an Id and a privilege enum.
The group has an id and a name.
I wonder how to model a relationship where an user can be in multiple groups, having different privilege levels in different groups. Every group can of course have multiple members.
What's the way I'm supposed to solve that idiomatically with Hibernate?
Adding some membership field to User? A membership field to Group? Both? Creating a new class for it? Which annotations are required to wire these things together?
I used next architecture
UserEntity class
#Entity
#Table(name = "user")
public class UserEntity implements Serializable {
private Long user_id;
private String username;
private String password;
public UserEntity() {
}
public UserEntity(String name, String passwd) {
username = name;
password = passwd;
}
#Column(name = "password", nullable = false)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getUser_id() {
return user_id;
}
public void setUser_id(Long user_id) {
this.user_id = user_id;
}
#Column(name = "username", nullable = false)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
AuthorityEntity class
#Entity
#Table(name = "authority_role")
public class AuthorityEntity implements Serializable {
private Integer id;
private String authority;
private List<UserEntity> people;
public AuthorityEntity() {
}
public AuthorityEntity(String authString) {
authority = authString;
}
#Column(name = "authority", nullable = false)
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToMany(targetEntity = UserEntity.class,
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "authority_role_people",
joinColumns =
#JoinColumn(name = "authority_role_id"),
inverseJoinColumns =
#JoinColumn(name = "user_id"))
public List<UserEntity> getPeople() {
return people;
}
public void setPeople(List<UserEntity> people) {
this.people = people;
}
}
In fact - this is how implemented spring security plugin.
In your case you can implement that architecture, which will be more useful for you.