Spring3.1とHibernate4を使用してプロジェクトをセットアップしようとしています。オンラインでいくつかのチュートリアルに従っています。 Springフォーラムによると、Spring3.1で修正されるべきだったという奇妙なエラーが発生しています。 春のバグトラッカー
私のサービスがgetCurrentSession()
を呼び出すと、次の例外がスローされます。
org.hibernate.HibernateException: **No Session found for current thread**] with root cause org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.Java:97) at
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.Java:881)
****編集:Spring Spring 3.1 Documentation for Transactions に従って私のspring-dao.xmlを更新しました。データソースをorg.Apache.commons.dbcp.BasicDataSourceと交換してみました。これを引き起こしている可能性のある、構成から欠落しているプロパティはありますか? ****
これが私のspring-dao.xmlです:
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<value>hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect</value>
</property>
</bean>
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}"
p:user="${app.jdbc.username}"
p:password="${app.jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" />
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
マイユーザーBean(User.Java)
package com.foo.lystra.beans;
import Java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="users")
public class User implements Serializable {
private static final long serialVersionUID = -5527566191402296042L;
@Id
@Column(name = "idusers")
private Integer user_id;
@Column(name="login_name")
private String loginName;
@Column(name="password")
private String password;
@Column(name="role")
private String role;
@Column(name="congregation_id")
private Integer congregation_id;
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public Integer getCongregation_id() {
return congregation_id;
}
public void setCongregation_id(Integer congregation_id) {
this.congregation_id = congregation_id;
}
public String toString() {
return "user_name: " + this.loginName + " congregation_id: " + this.congregation_id.toString();
}
}
そして最後に私のサービス...
package com.foo.lystra.services;
import Java.util.List;
import javax.annotation.Resource;
import org.Apache.commons.logging.LogFactory;
import org.Apache.commons.logging.Log;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.foo.lystra.beans.User;
import com.foo.lystra.beans.Congregation;
@Service("congregationUserService")
@Transactional
public class CongregationUserService {
protected static Log logger = LogFactory.getLog(CongregationUserService.class);
@Resource(name="sessionFactory")
private SessionFactory sessionFactory;
public List<User> getAllUsers() {
logger.debug("getting all users");
//Exception is thrown on this next line:
Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("FROM users");
return query.list();
}
}
私のデータソースはおそらく使用されていないことに気づきました。構成を含めるのを忘れた場合は、この投稿を更新できます。また、Tomcatの起動ログが必要な場合は、それらも提供できます。
Spring-4.0.6とhibernate-4.3.6でこの問題が発生しました。
解決策は、すべてのアノテーション駆動型、コンポーネントスキャン、アノテーション駆動型ディレクティブをroot-context.xmlからservlet-context.xmlに移動することです。
<mvc:annotation-driven />
<context:component-scan base-package="ru.dd.demo" />
<tx:annotation-driven transaction-manager="transactionManager" />
dataSource、sessionFactory、transactionManagerは、root-context.xmlで引き続き定義できます。
Webアプリケーションでも同じ問題が発生します。問題は、application-context.xmlとwebmvc-context.xmlの両方の構成ファイルに存在することです。 webmvc-context.xmlは、application-context.xmlの後にロードされます。 DAOクラスは、application-context.xmlがロードされるときに最初にトランザクション参照でロードされると思いますが、webmvc-context.xmlがロードされると、トランザクション参照なしで別のオブジェクトに置き換えられます。とにかく、スキャンした特定のパッケージの問題を解決します。<context:component-scan base-package="com.app.repository" />
application-context.xmlの場合、および<context:component-scan base-package="com.app.web" />
webmvc-context.xmlの場合。
私はあなたと同じエラーがありました。
これはまだ解決されていないバグです。
https://jira.springsource.org/browse/SPR-9028
Hibernatejarファイルを3.6に変更してみてください。春がそれを使うからです。
http://mvnrepository.com/artifact/org.springframework/spring-orm/3.1.0.RELEASE
ここでSpring3.1のアーティファクトと依存関係
それはWebアプリケーションですか?その場合は、OpenSessionInViewFilterの使用を検討してください。原因currentSession(現在のスレッドにバインドされている)を使用する場合、セッションをスレッドからバインド解除するポイントがコード内にある必要があると思います。
トランザクションマネージャーがこれを行うかどうかはわかりません。
Spring Reference (3.2.x)で述べられているように:
Web MVCフレームワークでは、各DispatcherServletには独自のWebApplicationContextがあり、ルートWebApplicationContextですでに定義されているすべてのBeanを継承します。これらの継承されたBeanは、サーブレット固有のスコープでオーバーライドでき、特定のサーブレットインスタンスに対してローカルな新しいスコープ固有のBeanを定義できます。
したがって、<context:component-scan>
で定義またはスキャンされたBeanは、@ Autowiredできるようにコントローラーに表示されますが、他のapplicationContext *ファイルには表示されないため、DispatcherServletの構成で<tx:annotation-driven/>
が定義されていない限り、 @ Transactionalは機能しません。
したがって、おそらくDispatcherServletの設定に<context:component-scan>
があり、applicationContext * .xmlに<tx:annotation-driven/>
宣言があると思います。したがって、@ Autowiredは正常に機能しますが、@ Transactionalは機能しません。
私は同じ問題を抱えており、回答されたすべてのソリューションをテストしました。ヴァリの答えはとても役に立ちました。私にとってうまくいったのは、これらのBeanをapplicationContext.xmlからweb-servlet.xmlに移動することでした。
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
また、web-servlet.xmlに追加する必要があります。
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
"
Web.xmlにOpenSessionInViewFilterフィルターを追加します
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
この問題は、他のxml構成ファイルの代わりにdispatcher-servlet.xmlに<tx:annotation-driven transaction-manager="miTransactionManager"/>
を配置することで解決しました。
このようにして、同じ春の状況で豆が共存できるようになると思います。
この問題は春のバグであることがわかりました
このリンク https://jira.springsource.org/browse/SPR-902 問題を報告します。
これを修正するために、このリンクにあるMatias Mirabelliの回避策を使用しました https://Gist.github.com/seykron/4770724
何が起こっているのかというと、Propagation.SUPPORTS
アノテーションが付けられたメソッドはトランザクションをサポートしますが、スレッドにバインドされたトランザクションがない場合、新しいセッションを作成する代わりに、スプリングはHibernateException
をスローします。
ソリューションを構成するには、hibernateプロパティを使用できます。
hibernate.current_session_context_class = com.your.package.TransactionAwareSessionContext
まったく同じエラーが発生しましたが、サービス用にinterfaceを作成するだけで解決しました。したがって、あなたの場合、私は以下を作成します:
public interface ICongregationUserService {
public List<User> getAllUsers();
}
次に、CongregationUserServiceを変更して実装します。
@Service("congregationUserService")
@Transactional
public class CongregationUserService implements ICongregationUserService{
//...
}
congregationUserServiceを自動配線した場合は、代わりにICongregationUserServiceを自動配線します。
@Autowired
private ICongregationUserService congregationUserService;
構成が注釈付きクラスを指していません。それらを追加します
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<value>hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect</value>
</property>
<property name="annotatedClasses">
<list>
<value>test.package.Foo</value>
<value>test.package.Bar</value>
</list>
</property>
</bean>
これは、以前にあった AnnotationSessionFactoryBean に似ています。 Apiを確認してください ここ 。
よくわかりませんが、問題はp:packagesToScan
にある可能性があります。 ConfigurationUserServiceはパッケージcom.foo.lystra.services
にありますが、p:packagesToScan
にはcom.foo.lystra.beans
があります
私はあなたが必要だと信じています:
<context:component-scan base-package="com.foo.package" />
そうしないと、Springコンテキストでサービスが見つからないため、メソッドがトランザクションの側面でラップされません。
<context:component-scan base-package="com.sprhib.repo"/> #(some class files are annotaed by @Repository,@Service,@Component)
<tx:annotation-driven transaction-manager="txManager" />
<task:annotation-driven/>
root.xmlをintします。
<context:component-scan base-package="com.sprhib.web"/> #(some class files are annotaed by @Controller)
<mvc:annotation-driven />
intservlet-context.xml。
できます。