Я предлагаю вам сделать это (кажется Hacky, но с унаследованным кодом, это иногда требуется)
Это решение использует весну TransactionSynchronizationManager и Hibernate 4, но может быть адаптирована к другой версии Hibernate.
Вот эта идея: использование пользовательской реализации CurrentSessionContext в вашем SessionFactoryBean, и эта пользовательская реализация будет искать в транзакционных ресурсах для менеджера сущностей текущей транзакции; когда он найден, просто вызывает код, отправленный IIla для получения сеанса спящего режима.
Чтобы сделать это:
1.Define Свойство hibernate.current_session_context_class
в hibernateProperties:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
...
<property name="hibernateProperties">
<props>
...
<prop key="hibernate.current_session_context_class">
com.example.jpa.HibernateSessionInEntityManager
</prop>
</props>
</property>
</bean>
<!-- for completness : here are the other relevant beans -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.example.jpa.validator"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
2.Implement ваш собственный CurrentSessionContext: HibernateSessionInEntityManager.java
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.context.spi.CurrentSessionContext;
import org.hibernate.ejb.EntityManagerImpl;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.persistence.EntityManager;
import java.util.Map;
public class HibernateSessionInEntityManager implements CurrentSessionContext {
public HibernateSessionInEntityManager() {
}
public HibernateSessionInEntityManager(SessionFactory sessionFactory) {
}
public HibernateSessionInEntityManager(SessionFactoryImplementor sessionFactory) {
}
public Session currentSession() throws HibernateException {
Map<Object, Object> resourceMap = TransactionSynchronizationManager.getResourceMap();
for(Object v:resourceMap.values()){
if(v instanceof EntityManagerHolder){
return getSessionFromEM(((EntityManagerHolder)v).getEntityManager());
}
}
return null;
}
private static Session getSessionFromEM(final EntityManager entityManager)
{
final Object emDelegate = entityManager.getDelegate();
if (emDelegate instanceof EntityManagerImpl)
{
return ((EntityManagerImpl) emDelegate).getSession();
}
else if (emDelegate instanceof Session)
{
return (Session) emDelegate;
}
throw new HibernateException("No Session found");
}
}
Примечание все эти конструкторы: Hibernat e-4 нуждается в одном с SessionFactoryImplementor
, и я думаю, что Hibernate-3 нуждается в одном с SessionFactory
. (Конструктор не-арг, вероятно, не требуется)
3.Here простой тест, чтобы проверить, что он работает
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:ApplicationContext.xml" })
public class HibernateSessionInEntityManagerTest {
@Autowired
public SessionFactory sessionFactory;
@Test
@Transactional
public void testGetHibernateSession(){
Session session = sessionFactory.getCurrentSession();
Assert.assertNotNull(session);
}
}
Я надеюсь, что это поможет. (BTW: хороший вопрос)
Важное замечание: если у вас есть несколько EntityManagerFactoryBean, вы можете выбрать хороший, изучая транзакционные ресурсы. (То есть, например, посмотреть на persistenceUnitName присоединенной EntityManagerFactory)
пожалуйста, напишите код, связанный с управлением транзакциями (часть контекста XML-приложений, примеры кода с @Transactional annotation или xml-объявление транзакционных методов, если вы используете это) – ben75
Я написал в своем вопросе ** даже код, приведенный выше, был выполнен в транзакционном блоке. ** Таким образом, исключение происходит даже с кодом @Transactional annotation или xml-декларированием транзакционных методов – nir
Да ... но вы проверили, что транзакция действительно началась?- вы можете проверить это, просто включив соответствующий логгер (возможно, что @Transactional ничего не делает, если что-то плохо конфигурирует где-то в другом месте.) – ben75