我想将我的axis2项目与spring集成在一起。我按照本指南加载了一个spring applicationContext。
https://axis.apache.org/axis2/java/core/docs/spring.html
简而言之
以下是我的axis2版本服务:
public class VersionService extends MyappService{
private static final Logger log = Logger.getLogger(VersionService.class);
@Autowired
NewUserMyappDAO newUserMyappDAO;
public Response getResponse(){
Response response = new Response();
UserMyapp ub = getTransaction();
return response;
}
@Transactional
public UserMyapp getTransaction(){
return newUserMyappDAO.findById(13);
}
}
问题:当轴调用 getResponse() 方法时,dao 设法获取注入的会话工厂(和Hibernate会话),但是当在方法之上使用@Transactional时,之前没有打开任何事务。这就是为什么我得到:
Caused by: org.hibernate.HibernateException: get is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:348)
at $Proxy45.get(Unknown Source)
at com.myapp.framework.model.dao.NewMyappDAO.findById(NewMyappDAO.java:35)
at com.myapp.ws.version.VersionService.getTransaction(VersionService.java:127)
at com.myapp.ws.version.VersionService.getResponse(VersionService.java:119)
我想要的是有一个getTransaction()方法,它会自动启动事务(Hibernatesession.beginTransaction()),并在其中出现故障时回滚。
我也试着移除
<prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop>
但是在这种情况下,spring无法加载userMyAppDAO,因为org . hibernate . hibernate exception:没有为当前线程找到会话
详细来说,我的applicationContext.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:annotation-config />
<context:component-scan base-package="com.myapp.framework.model.dao"></context:component-scan>
<!-- Axis2 Web Service, but to Spring, its just another bean that has dependencies -->
<bean id="versionService" class="com.myapp.ws.version.VersionService"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://db.myapp.com:3307/MyappAPI" />
<property name="username" value="myapp" />
<property name="password" value="myappculomyapp" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.myapp.framework.model.dao</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.connection.CharSet">utf8</prop>
<prop key="hibernate.connection.characterEncoding">utf8</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.globally_quoted_identifiers">true</prop>
<prop key="hibernate.connection.autocommit">false</prop>
<prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
这是DAO及其超类:
@Repository
public class NewUserMyappDAO extends NewMyappDAO<UserMyapp, Integer>{
@Autowired
public NewUserMyappDAO(SessionFactory sessionFactory){
super(UserMyapp.class, sessionFactory);
}
}
@Repository
public abstract class NewMyAppDAO<E, ID extends Serializable>
implements IMyAppDAO<E, ID> {
private final Class<E> entityClass;
protected Session session;
public NewMyAppDAO(Class<E> entityClass, SessionFactory sessionFactory) {
this.entityClass = entityClass;
this.session = sessionFactory.getCurrentSession();
}
public Class<E> getEntityClass() {
return entityClass;
}
@SuppressWarnings({ "unchecked" })
public E findById(ID id) {
Object obj = null;
try {
obj = session.get(getEntityClass(), id);
} catch(ObjectNotFoundException e){
return null;
}
return (E) obj;
}
编辑
vp8106留下的答案似乎是正确的,但我试图后退一步,尝试以编程方式管理事务。我所做的是在getResponse()方法中显式使用beginTransaction()、commitTransaction。即使sessionFactory对象是单例对象,并且用初始化
<prop key="hibernate.current_session_context_class">thread</prop>
没有启动任何事务,我的dao仍然返回相同的异常。
多亏了vp816和M.Deinum,我才明白发生了什么。
>
这里最大的错误是我每次调用NewMyAppDAO的findById方法时都使用相同的私有会话字段对象。使用受保护的get会话()方法允许正确使用会话。
@Repository公共抽象类NewMyAppDAO实现IMyAppDAO{
private final Class<E> entityClass;
protected SessionFactory sessionFactory;
public NewMyAppDAO(Class<E> entityClass, SessionFactory sessionFactory) {
this.entityClass = entityClass;
this.sessionFactory = sessionFactory;
}
protected Session getSession(){
return this.sessionFactory.getCurrentSession();
}
}
使用程序化事务管理,我们必须设置属性
<prop key="hibernate.current_session_context_class">thread</prop>
Spring设置:
<tx:annotation-driven>
在这种情况下毫无用处。
如果我们想要使用spring注释驱动的事务,我们必须:< br> a)从sessionFactory bean配置中删除< code > hibernate . current _ session _ context _ class 属性< br> b)添加Spring设置< code >
@Service公共类版本处理程序 {
@Autowired
NewUserMyappDAO newUserMyappDAO;
@Transactional
public UserMyapp getUserMyapp(int transactionId){
return newUserMyappDAO.findById(transactionId);
}
}
很可能是Axis调用了spring bean的< code>getResponse方法,而该方法没有标记< code>@Transactional。事实上,spring为beans创建了一个动态代理,它的方法用< code>@Transactional进行了注释。此代理包装对事务处理方法的调用,在目标方法执行之前启动事务,在目标方法执行之后提交。但是在您的情况下,方法< code>getResponse调用此bean的方法< code>getTransaction,而不是代理。因此,事务感知代码不会执行,也不会启动任何事务。< br>
最简单的解决方案是用< code>@Transactional而不是< code>getTransaction来标记< code>getResponse方法。注意:只有在spring生成的代理上调用< code>getResponse时,它才会起作用,这在您提供的stacktrace中并不清楚。
编辑
在Spring环境中,您应该使用
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
它将hibernate会话生命周期绑定到Spring的HibernateTransactionManager为了启动、提交或回滚事务,应使用HibernateTransactionManager的.getTransaction(…)
、提交(…)
或回滚(…)。要以编程方式管理事务,最好使用
TransactionTemplate
,它可以帮助您避免编写样板代码来开始、提交或回滚事务。
问题内容: 我正在尝试使用Spring @Transactional批注,但是在调用方法 findAll 时遇到问题,并且出现以下错误: 人DAO: 这是我的: 我尝试删除此行,但是又出现了一个错误,为什么这行不通? 问题答案: 您必须明确声明对事务管理器注释的支持 添加到您的配置中: tx是xmlns:tx =“ http://www.springframework.org/schema/tx”
在我的应用程序中,我有2个transactionManager,创建如下: 在同一个文件中,我有注释驱动的声明: 为了简化admin transactionManager的可用性,我创建了一个简单的注释: 这是我的带有事务注释的方法: 由于有接口,该方法是从另一个类调用的。bean由Spring@Autowired注释注入。jdbcTemplate对象是用以下代码创建的: 我的问题是当我执行jdb
问题内容: 我正在使用Spring注释来管理我的事务,如下所示: 我想知道如果忘记注释会发生什么: 当alertDAO实现如下时: 似乎Hibernate允许我从数据库中获取数据,即使没有注释也是如此。 这种粗心大意的后果是什么?可能发生的最坏情况是什么? 问题答案: 根据文档(Spring docs ),它仅仅是元数据,它表明方法或接口可以由“具有交易意识的”事物(例如)进行配置。 相信只有 t
我在我的应用程序中使用了Spring冬眠球衣。我想使用事务,因此我在服务图层中使用了 spring @Transactional 注记。这是我的Hibernate.cfg.xml: 我没有在这里使用session_context,所以Spring可以管理它。在我的应用程序Context.xml中,我定义了事务管理器: 所有与 /api/v1/* 匹配的 url 都映射到名为泽西岛的服务器和使用的
问题内容: 之间有什么区别? 在整个类中添加“ @Transactional”注释 为每个方法添加“ @Transactional”注释? 使用spring和Hibernate吗? 问题答案: 基本上,如果您用所有方法注释该类,则将是事务性的。如果您不这样做,则可以仅将其标注为所需的方法。此外,你可以为每个方法指定不同的属性,如,,,…
问题内容: 我正在创建应用程序并在其中使用一些hibernate的东西。我要做的就是将实体保存到数据库中,但我不断收到此异常: 起初,我遇到了这个异常: 然后,我发现需要将其添加到我的hibernate配置中: 这解决了这个问题,但是现在出现了上面的问题。我将实体保存到这样的数据库中: 我的hibernate.cfg.xml文件如下所示: 我在用: Hibernate-4.1.4.Final JD