0

我正在使用 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>

我有两张表:原因和评论。

原因表有 3 列:

  1. ID - PK 是否使用序列填充。
  2. 代码 - 对其具有唯一约束,并且是一个 varchar 字段。
  3. 说明 - 带文本的 varchar

评论表有 4 列:

  1. ID - PK 是否使用序列填充。
  2. ReasonCode - 有一个带有原因表的 FK。
  3. Order - Integer - 具有唯一约束和原因代码。
  4. 注释 - 带文本的 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() {

我还在创建一个业务服务层并为其创建测试脚本。业务服务层有两种方法:

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);

我遇到了一个问题,hibernate 忽略了由“addFetch”指定的内部连接,并单独检索所有原因。我有点解决了它,但不明白为什么它会这样工作。

有两种解决方案:

  1. 我更改了测试脚本的顺序。因此,我不是先检索 AllReasons,而是先检索 AllComments,然后再检索 allReasons。在这种情况下,内部联接得到尊重,并且不会单独检索原因。
  2. 我在 Comments 业务方法上将事务传播从 REQUIRED 更改为 REQUIRES_NEW。在这种情况下,内部联接得到尊重,并且不会单独检索原因。

显然问题与共享事务和检索顺序有关,但我不知道为什么。有人对我有一些见解吗?

非常感谢。

4

0 回答 0