Map external id to local id - java

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

Related

Cannot resolve column when using inverseJoinColumns

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;
}
}

How to ignore spesific child properties on JSON response using #JsonIgnoreProperties?

I have 2 model classes named masterclient and userexternal
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name = "user_external")
public class UserExternalModel extends AuditModel {
#Id
#GeneratedValue(generator = "user_external_generator")
#SequenceGenerator(
name = "user_external_generator",
sequenceName = "user_external_sequence",
initialValue = 1
)
#Column(name = "user_id", nullable = false)
private long userId;
#NotBlank
#Size(min = 1, max = 65)
#Column(name = "name", nullable = false)
private String name;
#NotBlank
#javax.validation.constraints.Email
#Size(min = 1, max = 65)
#Column(name = "email", nullable = false)
private String email;
#Column(name = "active")
private int active;
#Column(name = "inactive_by", nullable = true)
private int inactiveBy;
#Column(name = "phone_number", nullable = true)
#Size(min = 1, max = 15)
private String phoneNumber;
#Column(name = "password", nullable = true)
#Size(min = 1, max = 65)
private String password;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#MapsId("client_id")
#JoinColumn(name = "clientId", referencedColumnName = "client_id")
private MasterClientModel masterClientModel;
private long clientId;
#OneToMany(mappedBy = "userExtModel", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
Set<EngagementUserExtModel> engUserExts = new HashSet<>();
public UserExternalModel() {
}
// Getters and Setters (Omitted for brevity)
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
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 int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public int getInactiveBy() {
return inactiveBy;
}
public void setInactiveBy(int inactiveBy) {
this.inactiveBy = inactiveBy;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public MasterClientModel getMasterClientModel() {
return masterClientModel;
}
public void setMasterClientModel(MasterClientModel masterClientModel) {
this.masterClientModel = masterClientModel;
}
public long getClientId() {
return clientId;
}
public void setClientId(long clientId) {
this.clientId = clientId;
}
}
then
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.Size;
import org.hibernate.annotations.Type;
#Entity
#Table(name = "master_client")
public class MasterClientModel extends AuditModel {
#Id
#GeneratedValue(generator = "master_client_generator")
#SequenceGenerator(
name = "master_client_generator",
sequenceName = "master_client_sequence",
initialValue = 1
)
#Column(name = "client_id", nullable = false)
private long clientId;
#Size(min = 1, max = 15)
#Column(name = "npwp", nullable = false)
private String npwp;
#Size(min = 1, max = 65)
#Column(name = "company_name", nullable = false)
private String companyName;
#Lob
#Type(type="org.hibernate.type.BinaryType")
#Column(name = "logo", updatable = true, columnDefinition="image")
private byte[] logo;
#Column(name = "description", nullable = true)
#Size(max = 255)
private String description;
#OneToMany(mappedBy = "masterClientModel", fetch = FetchType.LAZY)
Set<UserExternalModel> userExts = new HashSet<>();
#OneToMany(mappedBy = "masterClientModel", fetch = FetchType.LAZY)
Set<EngagementModel> engagements = new HashSet<>();
// Getters and Setters (Omitted for brevity)
public long getClientId() {
return clientId;
}
public void setClientId(long clientId) {
this.clientId = clientId;
}
public String getNpwp() {
return npwp;
}
public void setNpwp(String npwp) {
this.npwp = npwp;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public byte[] getLogo() {
return logo;
}
public void setLogo(byte[] logo) {
this.logo = logo;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
then when i called my API request on userexternal, given response as below :
{
"createdDate": "2020-06-18T08:24:17.263+00:00",
"updatedDate": "2020-06-18T08:24:17.263+00:00",
"userId": 1,
"name": "ZZZZZZZZZZZ",
"email": "aaaa#a.com",
"active": 1,
"inactiveBy": 2,
"phoneNumber": "123123123",
"password": "dualipa",
"masterClientModel": {
"createdDate": "2020-06-16T07:33:35.996+00:00",
"updatedDate": "2020-06-16T07:33:35.996+00:00",
"clientId": 1,
"npwp": "12312312312321",
"companyName": "PT A",
"description": "A",
"hibernateLazyInitializer": {}
},
"clientId": 1
}
My question is how i can remove some properties under "masterClientModel" such npwp, companyname, etc when i hit userexternal API request, but keep it visible/included when hit API Request from masterclientmodel.
i have tried with jsonignoreproperties value="npwp" but it not worked.
any help will be appreciate, thank you.
You can use #JsonIgnoreProperties on child field to ignore its properties
public class UserExternalModel extends AuditModel {
...
#JsonIgnoreProperties({"npwp", "companyName"})
private MasterClientModel masterClientModel;
}
Add #JsonIgnore on field
#Size(min = 1, max = 15)
#Column(name = "npwp", nullable = false)
#JsonIgnore
private String npwp;
use #JsonIgnore annotation on the property you want to exclude from response
example:
#Entity
#Table(name = "master_client")
public class MasterClientModel extends AuditModel {
#Id
#GeneratedValue(generator = "master_client_generator")
#SequenceGenerator(
name = "master_client_generator",
sequenceName = "master_client_sequence",
initialValue = 1
)
#Column(name = "client_id", nullable = false)
private long clientId;
#Size(min = 1, max = 15)
#Column(name = "npwp", nullable = false)
#JsonIgnore
private String npwp;
#Size(min = 1, max = 65)
#Column(name = "company_name", nullable = false)
private String companyName;
#Lob
#Type(type="org.hibernate.type.BinaryType")
#Column(name = "logo", updatable = true, columnDefinition="image")
private byte[] logo;
#Column(name = "description", nullable = true)
#Size(max = 255)
private String description;
#OneToMany(mappedBy = "masterClientModel", fetch = FetchType.LAZY)
Set<UserExternalModel> userExts = new HashSet<>();
#OneToMany(mappedBy = "masterClientModel", fetch = FetchType.LAZY)
Set<EngagementModel> engagements = new HashSet<>();
// Getters and Setters (Omitted for brevity)
public long getClientId() {
return clientId;
}
public void setClientId(long clientId) {
this.clientId = clientId;
}
public String getNpwp() {
return npwp;
}
public void setNpwp(String npwp) {
this.npwp = npwp;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public byte[] getLogo() {
return logo;
}
public void setLogo(byte[] logo) {
this.logo = logo;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

Spring is not using ManyToMany relationship

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

Tomcat loadbalancing serialize exception PersistenceExceptionTranslationInterceptor : lazy initialization exception

I have to put two tomcat servers (tcat01 and tcat02) in a loadbalancing architecture.
I'm using tomcat 6.x and I edited the conf/server.xml like this on tomcat tcat01 :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat01">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
....
On tcat02 conf/server.xml is like this :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcat02">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="6"/>
....
I started tcat01, and then tcat02, il catalina.out it seems that tcat01 communicates well with tcat02.
Then I connected to the webapp with internet navigator, and then each time I do something in the webapp (I mean when I navigate) there is this exception :
Nov 24, 2011 12:00:13 AM org.apache.catalina.core.ContainerBase backgroundProcess
WARNING: Exception processing manager org.apache.catalina.ha.session.DeltaManager#278c4835 background process
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mycompany.myproject.model.authentification.Authority.groups, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
And here is the code of the class which cannot be sezialized (ie the java bean mentioned in the stack trace) :
import static javax.persistence.GenerationType.IDENTITY;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
#Entity
#Table(name = "authority", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class Authority implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -7436593455923433675L;
//SYSTEM ROLE CONSTANT
public static final String MANAGER_SYSTEM_ROLE = "ROLE_MANAGER";
public static final String CLIENT_SYSTEM_ROLE = "ROLE_CLIENT";
public static final String PEDAGO_ADMIN_SYSTEM_ROLE = "ROLE_PEDAGO_ADMIN";
private Integer id;
#Size(min=1)
#Pattern(regexp="^ROLE[_a-zA-Z]+$", message="{authority.name.pattern.error}")
private String name;
#Size(max=65535)
private String description;
private Boolean isSystem;
private Set<Group> groups = new HashSet<Group>(0);
public Authority() {
this.isSystem = false;
}
public Authority(String name) {
this.name = name;
this.isSystem = false;
}
public Authority(String name, String description, Set<Group> groups) {
this.name = name;
this.description = description;
this.groups = groups;
this.isSystem = false;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "description")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIsSystem(Boolean isSystem) {
this.isSystem = isSystem;
}
#Column(name = "system")
public Boolean getIsSystem() {
return isSystem;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "group_authorities", joinColumns = { #JoinColumn(name = "authority_id", nullable = false, updatable = true) }, inverseJoinColumns = { #JoinColumn(name = "group_id", nullable = false, updatable = true) })
public Set<Group> getGroups() {
return this.groups;
}
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
#PrePersist
protected void updateSystemField() {
if(isSystem == null)
isSystem = false;
}
}
And here is the code of the java bean Group (cause we have a lazily initialize exception on a collection of Groups) :
import static javax.persistence.GenerationType.IDENTITY;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
#Entity
#Table(name = "groups", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class Group implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 7380068327050752558L;
private Integer id;
#NotNull
#Size(min=1)
private String name;
private String description;
private Boolean isSystem;
private Set<Authority> authorities = new HashSet<Authority>(0);
private Set<User> users = new HashSet<User>(0);
public Group() {
this.isSystem = false;
}
public Group(String name) {
this.name = name;
this.isSystem = false;
}
public Group(String name, String description, Set<Authority> authorities, Set<User> users) {
this.name = name;
this.description = description;
this.isSystem = false;
this.authorities = authorities;
this.users = users;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name", unique = true, nullable = false, length = 45)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "description")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public void setIsSystem(Boolean isSystem) {
this.isSystem = isSystem;
}
#Column(name = "system")
public Boolean getIsSystem() {
return isSystem;
}
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "group_authorities", joinColumns = { #JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { #JoinColumn(name = "authority_id", nullable = false, updatable = true) })
public Set<Authority> getAuthorities() {
return this.authorities;
}
public void setAuthorities(Set<Authority> authorities) {
this.authorities = authorities;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "group_users", joinColumns = { #JoinColumn(name = "group_id", nullable = false, updatable = true) }, inverseJoinColumns = { #JoinColumn(name = "user_id", nullable = false, updatable = true) })
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public void addAuthority(Authority authority) {
if(authorities == null)
authorities = new HashSet<Authority>(0);
authorities.add(authority);
}
public boolean removeAuthority(Authority authority) {
return authorities == null || authorities.remove(authority);
}
public void addUser(User user) {
if(users == null)
users = new HashSet<User>(0);
users.add(user);
}
public boolean removeUser(User user) {
return users == null || users.remove(user);
}
#PrePersist
protected void updateSystemField() {
if(isSystem == null)
isSystem = false;
}
}
Thanks for your help
You're getting the lazy instantiation exception since you have authority groups mapped as lazy. By the time the session is replicated, you're outside of an active session so it can't be hydrated. To remedy this, you have a few options:
Change your mapping so the association is fetched eagerly
Change your DAO to step into that collection (or use hibernate.initialize) to force the lazy load to occur before the session is closed
Detach the object from the session and then explicitly set the groups to null on the object before it is put into session to replace the hibernate proxy that is there.
For this particuar case, options 1 or 2 are probably the cleanest.

Hibernate : Use of #OneToMany or #ManyToMany targeting an unmapped class

i can't find where is my error, where i'm not mapping my class, but to me everything shoud be fine.. but isn't.
Can someone help me to find it ?
org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.bytecode.entities.Event.categorytagit[com.bytecode.entities.Categorytagit]
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1068)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:600)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:541)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:43)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1130)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:324)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
package com.bytecode.entities;
// Generated 29/03/2011 12:15:48 by Hibernate Tools 3.2.1.GA
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Event generated by hbm2java
*/
#Entity
#Table(name = "event", catalog = "tagit")
public class Event implements java.io.Serializable {
private Integer id;
private User user;
private String name;
private Date iniEventDate;
private Date iniInscDate;
private Date endInscDate;
private String urlPicture;
private Integer idEventoFacebook;
private String description;
private Integer places;
private Integer lottery;
private String street;
private String city;
private Integer idMainEvent;
private Set<Tag> tags = new HashSet<Tag>(0);
private Set<Presentparticipants> presentparticipantses = new HashSet<Presentparticipants>(0);
private Set<User> users = new HashSet<User>(0);
private Set<Categorytagit> categorytagit = new HashSet<Categorytagit>(0);
public Event() {
}
public Event(User user, String name, Date iniEventDate, String description, String street, String city) {
this.user = user;
this.name = name;
this.iniEventDate = iniEventDate;
this.description = description;
this.street = street;
this.city = city;
}
public Event(User user, String name, Date iniEventDate, Date iniInscDate, Date endInscDate, String urlPicture, Integer idEventoFacebook, String description, Integer places, Integer lottery, String street, String city, Integer idMainEvent, Set<Tag> tags, Set<Presentparticipants> presentparticipantses, Set<User> users, Set<Categorytagit> categorytagit) {
this.user = user;
this.name = name;
this.iniEventDate = iniEventDate;
this.iniInscDate = iniInscDate;
this.endInscDate = endInscDate;
this.urlPicture = urlPicture;
this.idEventoFacebook = idEventoFacebook;
this.description = description;
this.places = places;
this.lottery = lottery;
this.street = street;
this.city = city;
this.idMainEvent = idMainEvent;
this.tags = tags;
this.presentparticipantses = presentparticipantses;
this.users = users;
this.categorytagit = categorytagit;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "idOrganizer", nullable = false)
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "name", nullable = false, length = 55)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "iniEventDate", nullable = false, length = 19)
public Date getIniEventDate() {
return this.iniEventDate;
}
public void setIniEventDate(Date iniEventDate) {
this.iniEventDate = iniEventDate;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "iniInscDate", length = 19)
public Date getIniInscDate() {
return this.iniInscDate;
}
public void setIniInscDate(Date iniInscDate) {
this.iniInscDate = iniInscDate;
}
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "endInscDate", length = 19)
public Date getEndInscDate() {
return this.endInscDate;
}
public void setEndInscDate(Date endInscDate) {
this.endInscDate = endInscDate;
}
#Column(name = "urlPicture")
public String getUrlPicture() {
return this.urlPicture;
}
public void setUrlPicture(String urlPicture) {
this.urlPicture = urlPicture;
}
#Column(name = "idEventoFacebook")
public Integer getIdEventoFacebook() {
return this.idEventoFacebook;
}
public void setIdEventoFacebook(Integer idEventoFacebook) {
this.idEventoFacebook = idEventoFacebook;
}
#Column(name = "description", nullable = false, length = 65535)
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name = "places")
public Integer getPlaces() {
return this.places;
}
public void setPlaces(Integer places) {
this.places = places;
}
#Column(name = "lottery")
public Integer getLottery() {
return this.lottery;
}
public void setLottery(Integer lottery) {
this.lottery = lottery;
}
#Column(name = "street", nullable = false)
public String getStreet() {
return this.street;
}
public void setStreet(String street) {
this.street = street;
}
#Column(name = "city", nullable = false, length = 55)
public String getCity() {
return this.city;
}
public void setCity(String city) {
this.city = city;
}
#Column(name = "idMainEvent")
public Integer getIdMainEvent() {
return this.idMainEvent;
}
public void setIdMainEvent(Integer idMainEvent) {
this.idMainEvent = idMainEvent;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "event")
public Set<Tag> getTags() {
return this.tags;
}
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "event")
public Set<Presentparticipants> getPresentparticipantses() {
return this.presentparticipantses;
}
public void setPresentparticipantses(Set<Presentparticipants> presentparticipantses) {
this.presentparticipantses = presentparticipantses;
}
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "eventuser", catalog = "tagit", joinColumns = {
#JoinColumn(name = "idEvent", nullable = false, updatable = false)}, inverseJoinColumns = {
#JoinColumn(name = "idUser", nullable = false, updatable = false)})
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "eventcategory", catalog = "tagit", joinColumns = {
#JoinColumn(name = "idEvent", nullable = false, updatable = false)}, inverseJoinColumns = {
#JoinColumn(name = "idCategory", nullable = false, updatable = false)})
public Set<Categorytagit> getCategorytagit() {
return this.categorytagit;
}
public void setCategorytagit(Set<Categorytagit> categorytagit) {
this.categorytagit = categorytagit;
}
}
My hibernate.cfg:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:xxxx</property>
<property name="hibernate.connection.username">xxxxxxxxx</property>
<property name="hibernate.connection.password">xxxxxxxxxxxx</property>
<property name="hibernate.current_session_context_class">thread</property>
<!-- Connection pool C3P0 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">100</property>
<property name="hibernate.c3p0.timeout">20</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">60</property>
<!-- To show sql output on the screen -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- Mapping the entities -->
<mapping class="com.bytecode.entities.Categorytagit"/>
<mapping class="com.bytecode.entities.Likes"/>
<mapping class="com.bytecode.entities.Categoryfacebook"/>
<mapping class="com.bytecode.entities.Accountconfirmation"/>
<mapping class="com.bytecode.entities.User"/>
<mapping class="com.bytecode.entities.Tag"/>
<mapping class="com.bytecode.entities.PresentparticipantsId"/>
<mapping class="com.bytecode.entities.Company"/>
<mapping class="com.bytecode.entities.Event"/>
<mapping class="com.bytecode.entities.Presentparticipants"/>
</session-factory>
</hibernate-configuration>
UPDATE:
package com.bytecode.entities;
// Generated 29/03/2011 12:15:48 by Hibernate Tools 3.2.1.GA
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* Categorytagit generated by hbm2java
*/
#Entity
#Table(name = "categorytagit", catalog = "tagit")
public class Categorytagit implements java.io.Serializable {
private Integer id;
private String name;
private Set<Likes> likeses = new HashSet<Likes>(0);
private Set<Categoryfacebook> categoryfacebooks = new HashSet<Categoryfacebook>(0);
private Set<Event> events = new HashSet<Event>(0);
public Categorytagit() {
}
public Categorytagit(String name) {
this.name = name;
}
public Categorytagit(String name, Set<Likes> likeses, Set<Categoryfacebook> categoryfacebooks, Set<Event> events) {
this.name = name;
this.likeses = likeses;
this.categoryfacebooks = categoryfacebooks;
this.events = events;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name", nullable = false, length = 55)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "categorytagit")
public Set<Likes> getLikeses() {
return this.likeses;
}
public void setLikeses(Set<Likes> likeses) {
this.likeses = likeses;
}
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "categorytagit")
public Set<Categoryfacebook> getCategoryfacebooks() {
return this.categoryfacebooks;
}
public void setCategoryfacebooks(Set<Categoryfacebook> categoryfacebooks) {
this.categoryfacebooks = categoryfacebooks;
}
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "eventcategory", catalog = "tagit", joinColumns = {
#JoinColumn(name = "idCategory", nullable = false, updatable = false)}, inverseJoinColumns = {
#JoinColumn(name = "idEvent", nullable = false, updatable = false)})
public Set<Event> getEvents() {
return this.events;
}
public void setEvents(Set<Event> events) {
this.events = events;
}
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "idOrganizer", nullable = false)
public User getUser() {
return this.user;
}
I think you are missing target entity class to match your column.
#ManyToOne(targetEntity = User.class)

Categories