Как решить LazyinitializationException, не используя fetch = FetchType.EAGER? - PullRequest
3 голосов
/ 24 ноября 2010

Я все еще получаю исключение lazyinitializationexception. Да, я знаю, что это означает, что сессия закрыта, пока я или что-то еще пытаюсь получить доступ к коллекции. Нет, OpenEntityManagerInViewFilter не работает. Да, @ManyToOne (fetch = FetchType.EAGER) помог, но я не хочу его использовать, потому что он будет постоянно звучать беспорядочно.

Как еще я могу это сделать?

P.S. : Я использую HibernateEntityManger с jpa с аннотированным классом.

UPADATE вот мой код, в первую очередь У меня есть 4 таблицы: пользователей (идентификатор, first_name, last_name, электронная почта ....) роли (номер, имя, комментарий ....) users_roles (идентификатор_пользователь, ROLE_ID) почты (идентификатор, user_id, тема, сообщение, to_id ...)

Пользователь может иметь несколько ролей .... Пользовательский объект

@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  */

}

Роль Сущности

@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  */

}

почта

@ Entity @Table (name = "mails") Открытый класс Mail реализует 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;   }
}

пользовательский контроллер

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

почтовый контроллер

@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 для пользователя

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

При всем этом я редактирую .jsp для пользователя работает нормально с lazy = false. С FetchType.EAGER я не могу получить ни одну из моих писем, я вхожу в цикл stackovrflow, без FetchType.EAGER я получил это ленивое исключение.

Ответы [ 3 ]

2 голосов
/ 25 ноября 2010

удаление всех желающих и добавление этого решит мою проблему

    <mvc:interceptors>
    <bean class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor">  
        <property name="entityManagerFactory" ref="entityManagerFactory" />  
    </bean>
</mvc:interceptors>

фильтр не работал

2 голосов
/ 24 ноября 2010

OpenEntityManagerInViewFilter и OpenEntityManagerInViewInterceptor работают.Вы делаете что-то не так.

Кроме того, вы можете использовать Hibernate.initialize(..) для инициализации своих коллекций.Но делать это вручную не является предпочтительным.Подробно опишите, почему фильтр / перехватчик не работает.

Обновление: Вместо сопоставления фильтра с шаблоном сопоставьте его с сервлетом диспетчера.Поэтому вместо указания <url-pattern> specfiy <servlet-name>.

0 голосов
/ 25 ноября 2010

Прежде всего, проверьте, действительно ли вам нужно Collection, а не Set.Если объекты в коллекции уникальны, объявите переменную как Set, что решает 90% проблем с LazyInitializationException.

...