Hibernate 4.2.11 Final、Spring 3.2.4、および Google Genericdao 1.2.0 を使用しています。
私のSpringConfig.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:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- Specifying that this project is using annotation based Dependency Injection or IOC -->
<context:annotation-config />
<context:component-scan base-package="com.company" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@//URL:PORT/SERVICENAME" />
<property name="username" value="ID" />
<property name="password" value="Password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.company.client.hibernate.domain.Te</value>
<value>com.company.client.hibernate.domain.TeComment</value>
<value>com.company.client.hibernate.domain.TeReason</value>
<value>com.company.client.hibernate.domain.TeStatus</value>
<value>com.company.client.hibernate.domain.TeType</value>
<value>com.company.client.hibernate.domain.TeTypeToReasonMapping</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<aop:aspectj-autoproxy />
</beans>
理由とコメントの 2 つのテーブルがあります。
理由テーブルには 3 つの列があります。
- ID - シーケンスを使用して設定された PK です。
- コード - それに対して一意の制約があり、varchar フィールドです。
- 説明 - テキスト付きの varchar
コメント テーブルには 4 つの列があります。
- ID - シーケンスを使用して設定された PK です。
- ReasonCode - 理由テーブルを含む FK があります。
- 注文 - 整数 - には、それと理由コードに関する一意の制約があります。
- コメント - テキスト付きの varchar
Hibernate と Spring の両方にアノテーションを使用しています。
私の理由ドメインオブジェクトは
private BigDecimal reasonId;
private String reasonCode;
private String reasonDescription;
private List<TeComment> comments;
@Column(name = "REASON_ID", unique = true, nullable = false, precision = 22, scale = 0)
public BigDecimal getReasonId() {
@Column(name = "REASON_CODE", unique = true, nullable = false, length = 20)
public String getReasonCode() {
@Column(name = "REASON_DESCRIPTION", nullable = false, length = 1024)
public String getReasonDescription() {
@OneToMany (mappedBy = "reason")
public List<TeComment> getComments() {
私のコメント ドメイン オブジェクトには次のものがあります。
private BigDecimal commentId;
private String commentDescription;
private String reasonCode;
private BigDecimal commentOrder;
private TeReason reason;
@Column(name = "COMMENT_ID", unique = true, nullable = false, precision = 22, scale = 0)
public BigDecimal getCommentId() {
@Column(name = "REASON_CODE", nullable = false, length = 20, insertable=false, updatable=false)
public String getReasonCode() {
@Column(name = "COMMENT_DESCRIPTION", nullable = false, length = 1024)
public String getCommentDescription() {
@Column(name = "COMMENT_ORDER", nullable = false, precision = 22, scale = 0)
public BigDecimal getCommentOrder() {
@ManyToOne
@JoinColumn(name = "REASON_CODE", referencedColumnName = "REASON_CODE")
public TeReason getReason() {
また、ビジネス サービス レイヤーを作成し、そのテスト スクリプトを作成しています。ビジネス サービス層の 2 つのメソッドは次のとおりです。
public List<ReasonDTO> retrieveAllReasonsAsDTO();
public List<CommentDTO> retrieveAllCommentsAsDTO();
それらは次のように実装されます。
@Autowired
private TeCommentDAO teCommentDao;
@Autowired
private TeReasonDAO teReasonDao;
@Override
@Transactional (propagation=Propagation.REQUIRED, readOnly = true)
public List<ReasonDTO> retrieveAllReasonsAsDTO() {
return ConvertDomainDTO.convertTeReasonDomainToDTO_List(teReasonDao.findAll());
} // retrieveAllReasonsAsDTO
@Override
@Transactional (propagation=Propagation.REQUIRED, readOnly = true)
public List<CommentDTO> retrieveAllCommentsAsDTO() {
Search search = new Search(TeComment.class);
search.addFetch("reason");
List<TeComment> list = teCommentDao.search(search);
return ConvertDomainDTO.convertTeCommentDomainToDTO_List(list);
} // retrieveAllCommentsAsDTO
私のJUNITテストは次のとおりです。
List<ReasonDTO> allReasons = businessService.retrieveAllReasonsAsDTO();
assertEquals(allReasons.size(), beginningReasonSize);
List<CommentDTO> allComments = businessService.retrieveAllCommentsAsDTO();
assertEquals(allComments.size(), beginningCommentSize);
休止状態が「addFetch」によって決定された内部結合を無視し、すべての理由を個別に取得しているという問題があります。私はそれを解決しましたが、なぜこのように機能しているのかわかりません。
次の 2 つの解決策があります。
- テスト スクリプトの順序を変更します。したがって、最初に AllReasons を取得する代わりに、最初に AllComments を取得してから allReasons を取得します。この場合、内部結合が受け入れられ、理由は個別に取得されません。
- Comments ビジネス メソッドで、トランザクションの伝播を REQUIRED から REQUIRES_NEW に変更します。この場合、内部結合が受け入れられ、理由は個別に取得されません。
明らかに、問題はトランザクションの共有と取得の順序に関係していますが、その理由はわかりません。誰かが私に洞察を持っていますか?
どうもありがとう。