使用 FetchType.LAZY
时出现此错误无法写内容:懒得初始化一个集合 角色:com.websystique.springmvc.model.User.userProfiles,不可以 初始化代理 - 没有会话
这是我的模特课:
@SuppressWarnings("serial")
@Entity
@Table(name="APP_USER")
public class User implements Serializable{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@NotEmpty
@Column(name="SSO_ID", unique=true, nullable=false)
private String ssoId;
@NotEmpty
@Column(name="PASSWORD", nullable=false)
private String password;
@NotEmpty
@Column(name="FIRST_NAME", nullable=false)
private String firstName;
@NotEmpty
@Column(name="LAST_NAME", nullable=false)
private String lastName;
@NotEmpty
@Column(name="EMAIL", nullable=false)
private String email;
@NotEmpty
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "APP_USER_USER_PROFILE",
joinColumns = { @JoinColumn(name = "USER_ID") },
inverseJoinColumns = { @JoinColumn(name = "USER_PROFILE_ID") })
private Set<UserProfile> userProfiles = new HashSet<UserProfile>();
getters/setters ....
这是我的javascript ajax:
/* Populate DataTable of list of all User existed using ajax */
function populateUserDataTable() {
$("#dataTables-example").dataTable().fnDestroy();
/* set class and onClick event listener */
var buttonEditClass = 'class="btn btn-success" data-toggle="modal"';
buttonEditClass += 'data-target="#modalAddCargoUser"';
buttonEditClass += 'onClick="searchCargoDetailViaAjax(this)"';
var buttonDeleteClass = 'class="btn btn-danger" data-toggle="modal"';
buttonDeleteClass += 'data-target="#modalDeleteCargoUser"';
buttonDeleteClass += 'onClick="fetchDeleteId(this)"'
$
.ajax({
'url' : '' + myContext + '/ajaxUserList',
'method' : "GET",
'contentType' : 'application/json'
})
.done(
function(data) {
var dataToString = JSON.stringify(data);
$('#dataTables-example')
.dataTable(
{
responsive : true,
"aaData" : data,
"columns" : [
{
"data" : "firstName"
},
{
"data" : "lastName"
},
{
"data" : "email"
},
{
"data" : "ssoId"
},
{
/*
* Add button to
* dataTable
*/
sortable : false,
"render" : function(
data, type,
full, meta) {
var buttonID = full.ssoId;
var drawActionButton = ' <button id='
+ buttonID
+ ' '
+ buttonEditClass
+ ' >Edit</button> ';
drawActionButton += ' <button id='
+ buttonID
+ ' '
+ buttonDeleteClass
+ ' >Delete</button> ';
return drawActionButton;
}
} ]
})
});
}
我的控制器类:
/*
* This method will redirect user page
*/
@RequestMapping(value = { "/ajaxUserList" }, method = RequestMethod.GET)
@ResponseBody
public List<User> ajaxUserList(ModelMap model) {
/* Populate DataTable */
List<User> users = userService.findAllUsers();
model.addAttribute("loggedinuser", getPrincipal());
return users;
}
我的服务类:
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService{
@Autowired
private UserDao dao;
public List<User> findAllUsers() {
return dao.findAllUsers();
}
}
但是,当我更改 FetchType.EAGER 时,它可以正常工作。我也尝试阅读EAGER和LAZY之间的区别,我认为在我的情况下我更喜欢使用LAZY,因为它的内存使用量更少等。
还有其他方法如何使用LAZY让我的ajax工作?非常感谢任何帮助。
=============================================== ========================== 的更新
这是我的UserDaoImpl类:
@Repository("userDao")
public class UserDaoImpl extends AbstractDao<Integer, User> implements UserDao {
static final Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);
public User findById(int id) {
User user = getByKey(id);
if(user!=null){
Hibernate.initialize(user.getUserProfiles());
}
return user;
}
@SuppressWarnings("unchecked")
public List<User> findAllUsers() {
Criteria criteria = createEntityCriteria().addOrder(Order.asc("firstName"));
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);//To avoid duplicates.
List<User> users = (List<User>) criteria.list();
// No need to fetch userProfiles since we are not showing them on list page. Let them lazy load.
// Uncomment below lines for eagerly fetching of userProfiles if you want.
/*for(User user : users){
Hibernate.initialize(user.getUserProfiles());
}*/
return users;
}
}
AbstractDao类:
public abstract class AbstractDao<PK extends Serializable, T> {
private final Class<T> persistentClass;
@SuppressWarnings("unchecked")
public AbstractDao() {
this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass()
.getGenericSuperclass()).getActualTypeArguments()[1];
}
@Autowired
private SessionFactory sessionFactory;
protected Session getSession(){
return sessionFactory.getCurrentSession();
}
@SuppressWarnings("unchecked")
public T getByKey(PK key) {
return (T) getSession().get(persistentClass, key);
}
public void persist(T entity) {
getSession().persist(entity);
}
public void delete(T entity) {
getSession().delete(entity);
}
public void update(T entity){
getSession().update(entity);
}
protected Criteria createEntityCriteria(){
return getSession().createCriteria(persistentClass);
}
}
@ Bushra Hannure谢谢你,我不小心撞到了Dao中的代码我启用了
for(User user:users){ 状态,Hibernate.initialize(user.getUserProfiles()); }
然后再次将FetchType更改为LAZY,我可以毫无问题地使用我的ajax调用。对不起我的noob问题。
但是我无法承认它是如何覆盖该方法的。它说获取将是EAGERLY但我完全不明白。但不知何故,即使现在模型类将其设置为LAZY,它也能正常工作。
此代码的引用是链接:http://websystique.com/springmvc/spring-mvc-4-and-spring-security-4-integration-example/
答案 0 :(得分:0)
您的应用程序配置不允许在视图中使用Hibernate会话。在请求完成之后和渲染视图之前,会话正在关闭。
FetchType.EAGER在呈现视图和应用程序正常工作之前加载请求中的所有数据。 FetchType.LAZY按需加载数据 - 在视图中这样就可以获得Hibernate异常,因为此时会话已关闭。
例如,对于Spring Boot配置是:
spring.jpa.open-in-view: true