0

使用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/

4

1 回答 1

0

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

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

例如对于 Spring Boot 配置是:

spring.jpa.open-in-view: true
于 2018-04-25T07:35:08.600 回答