2014-10-09 1 views
1

У меня есть некоторые проблемы с пониманием того, как пружина управляет спящими сущностями и выполняет ленивый процесс загрузки.Жизненный цикл объекта спящего режима и период цикла сеанса внутри весенней транзакции

Так для этого случая мы должны субъектам

@Entity 
public class EntityA{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 


    @ManyToMany(cascade={CascadeType.PERSIST, CascadeType.REFRESH}) 
    private Collection<EntityB> bss= new ArrayList<EntityB>(); 

и agregated сущностей

@Entity 
public class EntityB{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 


    @ManyToMany(mappedBy="bss") 
    private Collection<EntityA> ass= new ArrayList<EntityA>(); 

тогда у меня есть простой бизнес-класс отмечен как транзакционные:

@Component 
@Scope("session") 
@Transactional(propagation=Propagation.TRIED_EVERY_SINGLE_ONE) 
public class GenericTestBean { 

    private EntityA entityA; 

    @Autowired 
    private IGenericDAO genericDAO; 


    public GenericTestBean() { 
     System.out.println("bean creado!"); 
    } 

    public void testQuery() { 
     entityA= genericDAO.get(EntityA.class, 1l); 
     System.out.println(TransactionIndicatingUtil.getTransactionStatus(true)); 
     System.out.println("is element atached? :" + genericDAO.isAtached(entityA)); 
     //this.loadData(); 

    } 

    public void loadData(){ 

     System.out.println(TransactionIndicatingUtil.getTransactionStatus(true)); 
     System.out.println("is element atached? :" + genericDAO.isAtached(currentCompany)); 

     System.out.println(entityA.getBss.size()); 
    } 

} 

и а Простой класс испытаний

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "applicationContext.xml" }) 
@WebAppConfiguration 
public class EntityQueryTest { 

// @Autowired 
// private SessionFactory sessionFactory; 

    @Autowired 
    GenericTestBean genericTestBean; 


    @Test 
    public void consultarCompania(){ 

     genericTestBean.testQuery(); 
     genericTestBean.loadData(); 
    } 

, что Im guessin что должно случиться: 1. GenericTestBean получает экземпляр 2. testQuery вызывается из-за пределов прокси запуска транзакции 2. LoadData называется, прокси-сервер видит активную транзакцию, и принимает сущее ресурсы 3. данные retrieived 4. transacion закрыт ...

Но это не происходит, кажется, есть две разные транзакции в каждом вызове метода, и объект получает отдельностоящий между вызовами, выдав ленивое исключение инициализации.

фактический журнал вывод заключается в следующем:

bean creado! --here the object get created 
Hibernate: select company0_.companyId as ..... --here the first query get executed 
[com.pe.controlLines.data.dao.GenericTestBean.testQuery] --here we check the name for the transaction 
is element atached? :true --and see if the element is attached to the session 
[com.pe.controlLines.data.dao.GenericTestBean.loadData] --this is in the second method call (with a different transaction name :O) 
is element atached? :false --both now, the same element get detached 

Я попытался повторно прикрепление сущности, но это дает мне новый запрос к базе данных (новый запрос к таблице EntityA посылаются плюс запрос, чтобы получить объекты, которые мне действительно не нравятся).

Im надеясь сохранить один дополнительный запрос только для того, чтобы иметь ленивую загрузку, или это должно быть так ?, или, может быть, у меня некорректная конфигурация?

Pdta: Я думаю, что опция фильтра просмотра даже хуже, чем опция повторного присоединения, это может привести к серьезным проблемам с производительностью при высоком уровне параллелизма.

Можно ли прояснить поведение контекстов транзакций между вызовами методов и как это связано с сеансом и состоянием сущностей?

реализация TransactionIndicatingUtil взята отсюда http://java.dzone.com/articles/monitoring-declarative-transac?page=0,1

и общий дао построен после того, как эта идея General or specific DAO to record delivery with information from multiple tables?

Update

в случае какого-либо использования, здесь весной конфигурации файл

<context:component-scan base-package="xxxxxx" /> 

    <context:annotation-config /> 
    <context:spring-configured /> 

    <aop:aspectj-autoproxy proxy-target-class="true"/> 

    <!-- Data Source Declaration --> 
    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
     <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 

     <property name="url" value="jdbc:mysql://localhost:3306/xxxx" /> 

     <property name="username" value="xxxxx" /> 
     <property name="password" value="xxxxx" /> 
     <property name="initialSize" value="2" /> 
     <property name="minIdle" value="0" /> 
     <property name="minEvictableIdleTimeMillis" value="120000" /> 
     <property name="maxActive" value="20" /> 
     <property name="maxWait" value="5000" /> 
    </bean> 

    <!-- Session Factory Declaration <bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> --> 
    <!-- Session Factory Declaration --> 
    <bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="myDataSource" /> 
     <property name="packagesToScan"> 
      <list> 
       <value>com.xx.xx.xx.xx</value> 
      </list> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
       <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.search.default.directory_provider">filesystem</prop> 
       <prop key="hibernate.search.default.indexBase">C:/DEVELOPMENT/lucene/indexes</prop> 


      </props> 
     </property> 
    </bean> 

    <!-- Enable the configuration of transactional behavior based on annotations --> 
    <tx:annotation-driven transaction-manager="txManager"/> 

    <!-- Transaction Manager is defined --> 
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="SessionFactory"/> 
    </bean> 
+0

Я не совсем уверен, что если вы говорите о (закомментирован) внутренний вызов из testQuery() в loadData(), но если вы тогда: http://stackoverflow.com/a/8233459/1356423 –

+0

Nop, на самом деле, когда я раскомментирую его, он работает так, как я ожидаю: s это может быть проблема с конфигурацией Spring Spring? –

ответ

0

Класс Test должен быть транзакционным слишком

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "applicationContext.xml" }) 
@Transactional // <--- add 
public class EntityQueryTest { 

Я предполагаю, что ваш файл applicationContext.xml это код XML показан в сообщении

+0

его аналогичный комментарий к другому варианту, если первый слой у меня есть xhtml, а не сам класс, как я это делаю? Я имею в виду, чтобы поддерживать транснациональное управление через различные вызовы (например, веб-мастер) –

+0

, пожалуйста, исправьте меня, если я ошибаюсь. пружинный прокси сам не является правым? он просто создает и удерживает транзакцию для каждого вызова метода. В случае, когда мы передали транзакцию через весь класс, сеанс будет поддерживать открытие базы данных, что приведет к очевидным проблемам. (может быть, это глупо) ... Theres способ переназначить новое соединение с существующими объектами без повторения запроса? Я мог бы быть на 100% уверен, что отдельные элементы, которые не могут быть изменены вообще параллельными сеансами, возможно каким-то образом? –

+0

** One **: Любой bean-компонент с '@ Transactional' завернут с прокси-сервером **, чтобы добавить ** транзакционную поддержку (методы должны быть общедоступными, а не уверены, работают ли и для защищенных). ** Два **: при запуске приложения Spring приложение «ApplicationContext» создается и управляет всеми компонентами. Рассмотрим Тестирование специального сценария, в котором вы должны указать Spring **, запустить ** эти методы '@ Test' с поддержкой Transaction, поэтому класс имеет' @ Transactional', где находятся в среде тестирования, а не в производственной/рабочей среде , –

0

Сам тест JUnit не является транзакционным. Каждый метод вашего компонента GenericTestBean является транзакционным. Таким образом, каждый раз, когда не транзакционный тест вызывает метод транзакционного компонента, запускается транзакция, выполняется метод bean-компонента, и транзакция выполняется. Поскольку вы последовательно вызываете два транзакционных метода, запускаются две отдельные транзакции.

Если сам метод тестирования был транзакционным, тогда для метода тестирования будет запущена транзакция и (по умолчанию), два метода bean будут выполняться в контексте существующей транзакции, начатой ​​тестом. Сделка будет завершена после возврата метода проверки.

+0

huuuum Я его получаю, но в последнем случае у меня есть jsp, как я могу сохранить транзакцию и соединение вживую, чтобы иметь одну транзакцию для многих операций? (также ленивый рабочий) –

 Смежные вопросы

  • Нет связанных вопросов^_^