Infinity loop when using findAll() Spring JPA PostgreSQL - java

Here is my entitiy:
#Entity
#Table(name = "remind")
public class Remind {
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
private long id;
#Column(name = "title", nullable = false, length = 50)
private String title;
#Column(name = "remind_date", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date remindDate;
public Remind() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getRemindDate() {
return remindDate;
}
public void setRemindDate(Date remindDate) {
this.remindDate = remindDate;
}
//---Dependency---->
#OneToOne(optional = false)
#JoinColumn(name="id_user", unique = true, nullable = true, updatable = false)
private Users user;
public void setUser(Users user) {
this.user = user;
}
public Users getUser() {
return user;
}
}
And here is another entity:
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue(generator = "increment")
#GenericGenerator(name = "increment", strategy = "increment")
private long id;
#Column(name = "name", nullable = false, length = 50)
private String name;
public Users() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String title) {
this.name = name;
}
//---Dependency---->
#OneToOne(optional = false, mappedBy="user")
public Remind remind;
public Remind getRemind() {
return remind;
}
public void setRemind(Remind remind) {
this.remind = remind;
}
Here is diagram that Idea shows me:
But when I use in RemindController.class:
#RequestMapping(value = "/get", method = RequestMethod.GET)
#ResponseBody
public List<Remind> getReminder() {
List<Remind> list = remindRepository.findAll();
return list;
}
I have this result... infinity loop:
What am I do wrong? It seems like diagram is ok. Help me please(

It's not jpa problem. It's a problem with serializing your entity to json. You need to explicitly mark the relation as bidirectional so the serializer can skip one end.
For Spring I'm assuming you're using jackson.
Take a look at answers to this question.

Related

Add Image Column in Broadleaf Admin Custom Entities

I added below mentioned custom entity for insert image from broadleaf admin console. But that image field not appear in the admin console. I added 'MEDIA' filed in my entity class. Please help me to solve this issue.
#Entity
#Table(name="MY_CUSTOM_CLASS")
#Inheritance(strategy = InheritanceType.JOINED)
#AdminPresentationClass(friendlyName = "MyCustomClass")
public class MyCustomClass implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(generator = "MyCustomClassId")
#GenericGenerator(
name="MyCustomClassId",
strategy="org.broadleafcommerce.common.persistence.IdOverrideTableGenerator",
parameters = {
#Parameter(name="segment_value", value="MyCustomClass"),
#Parameter(name="entity_name", value="com.community.core.domain.MyCustomClass")
}
)
#Column(name = "MY_CUSTOM_CLASS_ID")
protected Long id;
#Column(name = "NAME", nullable = false)
#AdminPresentation(friendlyName = "MyCustomClass_name", order = 1,
prominent = true, gridOrder = 1)
protected String name;
#ManyToOne(targetEntity = MediaImpl.class, cascade = {CascadeType.ALL})
#JoinColumn(name = "MEDIA_ID")
#ClonePolicy
protected Media media;
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 Media getMedia() {
return media;
}
public void setMedia(Media media) {
this.media = media;
}
}
Any help or workarounds are really appricated.
Put an #AdminPresentation annotation on the media field.

How to create multiple mapping of one table? (jpa hibernate)

Im creating an application in spring boot. I want to have multiple entity mapping for one table.
one entity retrieve the table without any join and the other entity retrieve the table with join.
This is the table schema:
book : {"id":1, "title":"math1", "author_id":1}
author: {"id":1, "name": "james"}
thank you.
Ive made it.
#MappedSuperclass
public abstract class BookBase<T extends BookBase> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false, updatable = false, name = "id")
private Integer id;
#Column(name = "title")
private String title;
public Integer getId() {
return this.id;
}
public T setId(Integer id) {
this.id = id;
return (T) this;
}
public String getTitle() {
return this.title;
}
public T setTitle(String title) {
this. title = title
return (T) this;
}
}
#Entity
#Table
public class Book extends BookBase<Book> {
#Column(name = "author_id")
private Integer authorId;
public Integer getAuthorId() {
return authorId;
}
public void setAuthorId(Integer authorId) {
this.authorId = authorId;
}
}
#Entity
#Table
public class BookJoinAuthor extends BookBase<BookJoinAuthor> {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "author_id")
private Author author;
public Author getAuthor() {
return author;
}
public void setAuthorId(Author author) {
this.author = author;
}
}
#Entity
#Table
public abstract class Author {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false, updatable = false, name = "id")
private Integer id;
#Column(name = "name")
private String name;
public Integer getId() {
return this.id;
}
public T setId(Integer id) {
this.id = id;
return (T) this;
}
public String getName() {
return this.name;
}
public T setName(String name) {
this. name = name
return (T) this;
}
}

Hiberate one-to-one annotaion builds wrong sql query

I have a small problem with hibernate query with one-to-one relation
I created 3 entities. In case of one-to-one relation user-to-group it works properly. I use property create in hiberanate config and it creates correct table with correct FK.
Creating record work correct too
MyUser user = new MyUser();
user.setLogin("Mark");
user.setPassword("123456");
MyPresence presence = new MyPresence();
presence.setPresenceId(2);
presence.setUser(user);
session.beginTransaction();
session.save(user);
session.save(presence);
session.getTransaction().commit();
session.close();
if get User by presence it works correct
int id = 2;
MyPresence myPresence = session.load(MyPresence.class, id);
System.out.println(myPresence);
But when I'm try to get presence by user result from database hibernate build wrong sql query
int id = 3;
MyUser myUser = session.load(MyUser.class, id);
System.out.println(myUser);
Generated Hibernate sql:
Hibernate: select myuser0_.id as id1_2_0_, myuser0_.group_id as group_id4_2_0_, myuser0_.login as login2_2_0_, myuser0_.password as password3_2_0_, mypresence1_.id as id1_1_1_, mypresence1_.presence_id as presence2_1_1_, mypresence1_.updated_at as updated_3_1_1_, mypresence1_.user_id as user_id4_1_1_ from users myuser0_ left outer join user_presence mypresence1_ on myuser0_.id=mypresence1_.id where myuser0_.id=?
But I expect to see
on myuser0_.id=mypresence1_.user_id instead of on myuser0_.id=mypresence1_.id
MyUser.java
#Entity
#Table(name = "users")
public class MyUser {
private int id;
private String login;
private String password;
private MyGroup group;
private MyPresence presence;
public MyUser() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "login")
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#JoinColumn(name = "group_id")
#OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
public MyGroup getGroup() {
return group;
}
public void setGroup(MyGroup group) {
this.group = group;
}
#OneToOne(cascade = CascadeType.DETACH)
#JoinColumn(name = "id", referencedColumnName = "user_id")
public MyPresence getPresence() {
return presence;
}
public void setPresence(MyPresence presence) {
this.presence = presence;
}
}
MyPresence.java
#Entity
#Table(name = "presence")
public class MyPresence {
private int id;
private MyUser user;
private int presenceId;
private Date updatedAt;
public MyPresence() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", referencedColumnName = "id")
public MyUser getUser() {
return user;
}
public void setUser(MyUser user) {
this.user = user;
}
#Column(name = "presence_id")
public int getPresenceId() {
return presenceId;
}
public void setPresenceId(int presenceId) {
this.presenceId = presenceId;
}
#Column(name = "updated_at")
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}

how to solve lazyinitializationexception not using fetch=FetchType.EAGER?

Iam still getting the exception lazyinitializationexception.
Yes, i know that it means, that the session is closed while I or something else is trying to access the collection.
No, the OpenEntityManagerInViewFilter did not work.
Yes, #ManyToOne(fetch=FetchType.EAGER) helped but i dont want to use it, cause it will fecth aumotically all the time.
How Else can i do that ?
P.S. : I am using HibernateEntityManger with jpa with annotated class.
UPADATE
here is my code, first of all
I have 4 tables :
users(id,first_name,last_name,email....)
roles(id,name,comment....)
users_roles(user_id,role_id)
mails(id,user_id,subject,message,to_id...)
An user can have mutiples roles ....
Users Entity
#Entity
#Table(name = "USERS")
public class User implements GenericDomain{
public static final String _ID = "id";
private Long id;
private String firstName;
private String lastName;
private String email;
private Set<Role> roles = new HashSet<Role>(0);
/* Constructors */
public User() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ID", unique = true, nullable = false)
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
#Column(name="FIRST_NAME", nullable = false, length = 64)
#NotEmpty
#Length(min = 4, max = 45)
public String getFirstName() { return this.firstName; }
public void setFirstName(String firstname) { this.firstName = firstname; }
#Column(name="LAST_NAME", nullable = false, length = 64)
#NotEmpty
#Length(min = 4, max = 45)
public String getLastName() { return this.lastName; }
public void setLastName(String lastname) { this.lastName = lastname; }
#Column(name="EMAIL", unique = false, length = 64)
#Email
#NotEmpty
#Length(min = 4, max = 45)
public String getEmail() { return this.email; }
public void setEmail(String email) { this.email = email; }
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name = "USERS_ROLES"
, joinColumns = { #JoinColumn(name = "user_id") }
, inverseJoinColumns = { #JoinColumn(name = "role_id") }
)
public Set<Role> getRoles() {
return this.roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
/*#Override toString/equals/hascode */
}
Role Entity
#Entity
#Table(name = "ROLES")
public class Role implements GenericDomain {
private Long id;
private String name;
private String comment;
private Set<User> users = new HashSet<User>(0);
public Role() {
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "ID", unique = true, nullable = false)
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
#Column(name="NAME", nullable = false, length = 64)
#NotEmpty
#Length(min = 1, max = 32)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
#Column(name="COMMENT", nullable = true, length = 256)
#Length(min = 0, max = 255)
public String getComment() { return this.comment; }
public void setComment(String comment) { this.comment = comment;}
#ManyToMany(cascade=CascadeType.REFRESH,fetch=FetchType.EAGER)
#JoinTable(
name = "USERS_ROLES"
, joinColumns = { #JoinColumn(name = "role_id") }
, inverseJoinColumns = { #JoinColumn(name = "user_id") }
)
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
/*#Override toString/equals/hascode */
}
mails
#Entity
#Table(name = "mails")
public class Mail implements GenericDomain{
private Long id;
private String mailSubject;
private String mailContent;
private Long receiverId;
private User user = null;
public Mail(){
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", nullable = false)
public Long getId(){ return this.id; }
public void setId(Long id){ this.id = id;}
#Column(name = "MAILSUBJECT", nullable = false, length = 63)
#Length(max = 63)
public String getMailSubject(){ return this.mailSubject; }
public void setMailSubject(String mailSubject){ this.mailSubject = mailSubject; }
#Column(name = "MAILCONTENT", nullable = true, length = 255)
#Length(max = 255)
public String getMailContent(){ return this.mailContent; }
public void setMailContent(String mailContent){ this.mailContent = mailContent; }
#Column(name = "RECEIVERID")
public Long getReceiverId(){ return this.receiverId; }
public void setReceiverId(Long receiverId){ this.receiverId = receiverId; }
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "USER_ID")
#NotNull
public User getUser(){ return this.user; }
public void setUser(User user){ this.user = user; }
}
user controller
#Controller
#RequestMapping("/admin/user")
#SessionAttributes("user")
public class UserController {
private UserService userService;
private RoleService roleService;
#Autowired
public UserController(UserService userService, RoleService roleService) {
this.userService = userService;
this.roleService = roleService;
}
#RequestMapping(value = "edit", method = RequestMethod.GET)
public String editUser(#RequestParam(value="id", required = true) Long id, ModelMap model) {
model.addAttribute("allRoles", roleService.getAll());
model.addAttribute("user", userService.getOne(id));
return "/admin/user/edit";
} }
mail controller
#Controller
#SessionAttributes("mail")
#RequestMapping("/portal/mail")
public class MailController{
#Autowired
private MailService mailService;
#RequestMapping(value = "ajaxLoad", method = RequestMethod.GET)
public #ResponseBody List<Mail> list(#RequestParam(value = "type", required = true) String type){
return mailService.getUserMails((Long) WebHelper.getPrincipal().getUser().getId(),type);
}
}
my web.xml
<filter>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
my edit.jsp for user
<select >
<c:forEach items="${allRoles}" var="role">
<option value="${role.id}" <c:if test="${fn:contains(roleSelected, role)}">selected="selected"</c:if> >${role.name}</option>
</c:forEach>
</select>
With all that, i edit.jsp for user is working fine with lazy=false.
With FetchType.EAGER am not able to get any of my mails, am getting into a cycle stackovrflow, without FetchType.EAGER i got that lazy exception.
removing all the eager and adding this solve my problem
<mvc:interceptors>
<bean class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</mvc:interceptors>
the filter didnt work
OpenEntityManagerInViewFilter and OpenEntityManagerInViewInterceptor work. You are doing something wrong.
Apart from that, you can use Hibernate.initialize(..) to initialize your collections. But doing this manually is not preferred. Give more details of why the filter/interceptor don't work.
Update: Instead of mapping the filter to a pattern, map it to the dispatcher servlet. So instead of specifying <url-pattern> specfiy <servlet-name>.
First of all, check if you really need Collection rather than Set. If objects within collection are unique, declare variable as Set, which solves 90% of issues with LazyInitializationException.

how to write delete query in hibernate for many to many relationship

I have two beans user and virtualdomain
#Entity
#Table(name = "tblUser")
public class User implements Serializable {
private Long id;
private String username;
private String deleteflag;
private Set<VirtualDomain> virtualdomainset;
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "username", length = 50, nullable = false)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "deleteflag")
public String getDeleteflag() {
return deleteflag;
}
public void setDeleteflag(String deleteflag) {
this.deleteflag = deleteflag;
}
#ManyToMany(targetEntity = VirtualDomain.class, cascade = {CascadeType.PERSIST},fetch=FetchType.EAGER)
#JoinTable(name = "tblUserDomainRel", joinColumns = #JoinColumn(name = "userid"), inverseJoinColumns = #JoinColumn(name = "domainid"))
public Set<VirtualDomain> getVirtualdomainset() {
return virtualdomainset;
}
public void setVirtualdomainset(Set<VirtualDomain> virtualdomainset) {
this.virtualdomainset = virtualdomainset;
}
}
#Entity
#Table(name = "tblVirtualDomain")
public class VirtualDomain {
private Long id;
private String domainname;
private String deleteflag;
private Set<User> userset;
#Id
#JoinColumn(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "domain_name")
public String getDomainname() {
return domainname;
}
public void setDomainname(String domainname) {
this.domainname = domainname;
}
#Column(name = "deleteflag")
public String getDeleteflag() {
return deleteflag;
}
public void setDeleteflag(String deleteflag) {
this.deleteflag = deleteflag;
}
#ManyToMany(cascade = {CascadeType.ALL},fetch=FetchType.EAGER, mappedBy = "virtualdomainset", targetEntity = User.class)
public Set<User> getUserset() {
return userset;
}
public void setUserset(Set<User> userset) {
this.userset = userset;
}
}
Now when I delete some user i use to set the deleteflag which means that the data remains in the database.
My requirement is that the user whose delete flag is set must be removed from the tblUserDomainRel table so how to write that delete query.
just remove the virtualDomain from the collection on the User and remove the other side for completeness
// on User
public void removeVirtualDomain(VirtualDomain vd){
virtualDomainset.remove(vd);
vd.getUserset().remove(this)
}
this will remove the relationship record. Or to remove a user from all virtual Domains:
// on User
public void removeFromAllVirtualDomains(){
for( VirtualDomain vd : virtualdomainset ){
vd.getUserset().remove(this);
}
virtualDomainset.clear();
}

Categories