2015-02-01 3 views
3

Проблема: не удается добавить Address объект через User объект внутри весны Controller.Hibernate - не удалось лениво инициализировать коллекцию роли - не удалось инициализировать прокси - нет Сессия

User и Address классы ->@Entity

User имеет List<Address> с FetchType=LAZY

@Repository 
public class UserDao{ 
    @Autowired 
    private SessionFactory sessionFactory; 
    ... 
    public User get(String username) { 
     Session session = sessionFactory.getCurrentSession(); 
     return (User)session.get(User.class, username); 
    } 
    ... 
    public void update(User user){ 
     Session session = sessionFactory.getCurrentSession(); 
     session.saveOrUpdate(user); 
    } 
    ... 
} 


@Service 
@Transnational 
public class UserService{ 
    @AutoWired 
    private UserDao userDao; 
    ... 

    @Transactional(readOnly = true) 
    public User get(String username) { 
     Session session = sessionFactory.getCurrentSession(); 
     return (User)session.get(User.class, username); 
    } 

    public void update(User user){ 
     userDao.update(user); 
    } 
    ... 
} 

@Controller 
public class UserController{ 
    @AutoWired 
    private UserService userService; 
    .... 
    public String update(){ 
     User user = userService.get("user0001"); 
     user.getAddressList.add(new Address("new street")); 
     return "update"; 
    } 
} 

Spring.xml

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="location"> 
     <value>classpath:jdbc.properties</value> 
    </property> 
</bean> 

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
    <property name="driverClass" value="${jdbc.driverClassName}" /> 
    <property name="jdbcUrl" value="${jdbc.url}" /> 
    <property name="user" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
</bean> 

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource"> 
     <ref bean="dataSource"/> 
    </property> 
    <property name="packagesToScan" value="com.entity" /> 
    <property name="hibernateProperties"> 
     <props> 
     <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
     <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
     </props> 
    </property> 
</bean> 

Все работает отлично. Но я не могу вносить изменения в объект user внутри @Controller.

Когда user объект получает изменение в @Controller уровне, такой сеанс Hibernate не связан с объектом. Так или иначе объект выходит из контекста спящего режима.

Ошибка в .add(new Address("new street")); заявление в @Controller.

Почему запрещено изменять объект внутри Controller, который получен через сеанс Hibernate?

Неправильно ли вы следовали за мной? Если не то, что я сделал неправильно?

--Spring 4, Hibernate 4

ответ

3

User имеет List<Address>. Когда вы выбираете пользователя из базы данных, а не списка, hibernate вставляет прокси-сервер, который обрабатывает выборку адресов.

Этот прокси должен иметь сеанс, чтобы иметь возможность делать что угодно. Когда вы пытаетесь добавить адрес, вы выходите за рамки транзакционной аннотации, поэтому сеанс отсутствует.

Лучший способ получить вас будет добавить метод, аннотированный @Transactional в UserService, который добавляет адрес.

+0

Да. Я пробовал, и это сработало. Можете ли вы немного объяснить в своем ответе про «прокси»? Не можем ли мы проинструктировать там прокси-серверы, чтобы НЕ отвечать сразу? Однако «Контроллер» понятия не имеет о прокси-сервере, который является спящим или что-то еще. Таким образом, существует правило соединения +, которое «не обновляет объекты/сущности внутри« Контроллеры ». Это нормально? – user2172625

+0

Вы используете одновременно две системы: Spring и Hibernate. Они оба делают вещи для вас, чтобы сделать вашу жизнь проще, но вам нужно понять, что делают каждый. Hibernate работает с концепцией транзакций. Вы создаете сеанс, выбираете некоторые объекты, изменяете их и передаете в базу данных, а затем закрываете сеанс. Если возникнут какие-либо исключения, откат и отмена. Это называется транзакцией. Вы можете узнать больше об этом здесь: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html – mpkorstanje

+0

Теперь, записывая весь этот код плиты котла каждый раз, это кровавая трата каждого времени , Таким образом, здесь появляется аннотация '@ Transactional'. Добавляя это к методу, вы указываете структуру (Spring в этом случае), чтобы обернуть код плиты котла для сеанса вокруг метода. – mpkorstanje