Не удалось записать содержимое: не удалось лениво инициализировать коллекцию ролей, не удалось инициализировать прокси - нет сеанса - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть эта ошибка при использовании 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? Любая помощь очень ценится.

=============================================== ========================== UPDATE

Вот мой класс 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);
    }



}

@ Бушра Ханнур, спасибо, я случайно ударил код в Дао, я включил

для (пользователь: пользователи) { Hibernate.initialize (user.getUserProfiles ()); }

затем снова измените FetchType на LAZY, и я могу без проблем использовать мой вызов ajax. извините за мой нубский вопрос.

Но я не могу понять, как он переопределил метод. в нем говорится, что получение будет ОЧЕНЬ, но я не могу полностью понять. но почему-то это работает даже сейчас, даже класс модели установил его в LAZY.

что касается ссылки на этот код, то здесь ссылка: http://websystique.com/springmvc/spring-mvc-4-and-spring-security-4-integration-example/

1 Ответ

0 голосов
/ 25 апреля 2018

Конфигурация вашего приложения не позволяет сеанс Hibernate в представлении. Сессия закрывается после выполнения запроса и перед отображением представления.

FetchType.EAGER загружает все данные по запросу ПЕРЕД визуализацией представления и приложение работает нормально. FetchType.LAZY загружает данные по требованию - здесь, в представлении, поэтому вы получаете исключение Hibernate, потому что в данный момент сеанс закрыт.

Например, для конфигурации Spring Boot:

spring.jpa.open-in-view: true
...