无法写入内容:无法延迟初始化角色集合,无法初始化代理 - 无会话

Posted

技术标签:

【中文标题】无法写入内容:无法延迟初始化角色集合,无法初始化代理 - 无会话【英文标题】:Could not write content: failed to lazily initialize a collection of role,could not initialize proxy - no Session 【发布时间】:2018-10-05 11:31:02 【问题描述】:

使用 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,因为它的内存使用量更少等。

还有其他方法可以让我的 ajax 使用 LAZY 工作吗?非常感谢任何帮助。

================================================ =========================== 更新

这是我的 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(用户用户:用户) Hibernate.initialize(user.getUserProfiles());

然后再次将 FetchType 更改为 LAZY,我可以毫无问题地使用我的 ajax 调用。对不起我的菜鸟问题。

但我无法理解它是如何覆盖该方法的。它说取货会很急,但我不能完全理解。但不知何故,即使现在模型类也将其设置为 LAZY。

至于此代码的参考是链接:http://websystique.com/springmvc/spring-mvc-4-and-spring-security-4-integration-example/

【问题讨论】:

请添加你的 DAO 类 【参考方案1】:

您的应用程序配置不允许视图中的 Hibernate 会话。会话在请求完成后和呈现视图之前关闭。

FetchType.EAGER 在渲染视图和应用程序正常工作之前加载请求中的所有数据。 FetchType.LAZY 按需加载数据 - 在视图中,您会收到 Hibernate 异常,因为此时会话已关闭。

例如对于 Spring Boot 的配置是:

spring.jpa.open-in-view: true

【讨论】:

以上是关于无法写入内容:无法延迟初始化角色集合,无法初始化代理 - 无会话的主要内容,如果未能解决你的问题,请参考以下文章

休眠延迟加载不适用于 Spring Boot => 无法延迟初始化角色集合无法初始化代理 - 无会话

org.hibernate.LazyInitializationException:无法延迟初始化角色集合:FQPropretyName,无法初始化代理 - 无会话

无法延迟初始化角色集合:myapp.myapp.models.Contact.messages,无法初始化代理 - 没有会话

LazyInitializationException: 延迟初始化角色集合失败 无法初始化代理 - 没有会话

未能延迟初始化角色集合:无法初始化代理 - Hibernate 中的 @ManyToMany 映射注释中没有会话错误? [复制]

延迟初始化:未能延迟初始化集合