简体   繁体   中英

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 ?

PS : 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.

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> .

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

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM