Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Spring 4.0和;休眠4.2.8_Spring_Hibernate_Transactions_Sequence_Isolation - Fatal编程技术网

使用Spring 4.0和;休眠4.2.8

使用Spring 4.0和;休眠4.2.8,spring,hibernate,transactions,sequence,isolation,Spring,Hibernate,Transactions,Sequence,Isolation,我们正在用Spring 4.0.0、Hibernate 4.2.8和Ms SQL Server 8开发一个应用程序,它使用一个自定义序列,该序列由DB表支持,并映射到Hibernate VO(CustomSequence) 此序列在服务调用中被访问: 主服务启动自己的事务 执行代码,做一些事情,查询 为序列值调用序列服务(SequenceService) SequenceService启动自己的事务(需要新的) SequenceService查找对象,返回值并保存下一个值 主服务获取值,在业务

我们正在用Spring 4.0.0、Hibernate 4.2.8和Ms SQL Server 8开发一个应用程序,它使用一个自定义序列,该序列由DB表支持,并映射到Hibernate VO(CustomSequence)

此序列在服务调用中被访问:

  • 主服务启动自己的事务
  • 执行代码,做一些事情,查询
  • 为序列值调用序列服务(SequenceService)

  • SequenceService启动自己的事务(需要新的)

  • SequenceService查找对象,返回值并保存下一个值

  • 主服务获取值,在业务对象中设置并保存(此时序列值已由内部新事务提交)

  • 出口
管理自定义序列的服务片段:

@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
@Service("sequenceService")
public class SequenceService implements ISequenceService {

    @Autowired
    private ISequenceDao sequenceDao;

    private Integer getSequence() {

        CustomSequence sequenceOut = sequenceDao.find();

        final Integer nextVal = sequenceOut.getNextVal();
        sequenceOut.setNextVal(nextVal + 1);
        sequenceDao.save(sequenceOut);

        return nextVal;    
    }    
}
我们的问题是serializable属性被完全忽略,所以两个并发线程访问getSequence方法并获得相同的值

如果我们使用TransactionSynchronizationManager检查隔离,该值对于serializable(值=8)似乎是正确的:

我们的spring xml文件如下所示:

<context:annotation-config />
<context:component-scan base-package="dev.app"/>
<tx:annotation-driven /> 

<bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/appDatasource"/>
</bean>    

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" lazy-init="false" >
    <property name="dataSource"> <ref bean="dataSource" /></property>
    <property name="packagesToScan" value="dev.app.model"/>
    <property name="hibernateProperties">
       <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <!-- Disable LOB creation as connection -->
            <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
        </props>
    </property>
 </bean>
有什么线索吗?我在网上读了很多信息,但都没有用


非常感谢

根据
HibernateTransactionManager
的代码,这可能是因为将事务管理器的prepareConnection标志设置为false:

/**
 * Set whether to prepare the underlying JDBC Connection of a transactional
 * Hibernate Session, that is, whether to apply a transaction-specific
 * isolation level and/or the transaction's read-only flag to the underlying
 * JDBC Connection.
 * <p>Default is "true". If you turn this flag off, the transaction manager
 * will not support per-transaction isolation levels anymore.  ...
 */
public void setPrepareConnection(boolean prepareConnection) {
    this.prepareConnection = prepareConnection;
}
isSameConnectionForEntireSession
表示:

/**
 * Return whether the given Hibernate Session will always hold the same
 * JDBC Connection. This is used to check whether the transaction manager
 * can safely prepare and clean up the JDBC Connection used for a transaction.
 * <p>The default implementation checks the Session's connection release mode
 * to be "on_close".
 */
protected boolean isSameConnectionForEntireSession(Session session) ...
/**
*返回给定的Hibernate会话是否始终保持不变
*JDBC连接。这用于检查事务管理器
*可以安全地准备和清理用于事务的JDBC连接。
*默认实现检查会话的连接释放模式
*要“接近”。
*/
受保护的布尔值isSameConnectionForEntireSession(会话会话)。。。
这意味着只有在以下情况下才能应用自定义隔离级别:在事务管理器上启用了执行此操作的标志,并且保证相同的数据库连接将始终用于相同的hibernate会话

如果不是这样,则事务管理器不会更改隔离设置,因为如果一个会话可以使用多个会话进行不同的查询,事务管理器将不知道会话何时被发送回池


这基本上意味着,如果事务管理器能够保证在将会话发送到池之前清除相同的设置,则它只能更改数据库会话的隔离设置。

谢谢您的回答。我已经调试了这个类,看起来一切正常,从某种意义上说,标志从未更改过(真值),isSameConnectionForEntireSession(会话)值也是真的。它进入DataSourceUtils.prepareConnectionForTransaction(con,definition)并将当前隔离设置为8(以前的隔离为2)。内部事务结束后,执行“doCleanupAfterCompletion”,恢复以前的隔离值(2)。我只是不知道这里出了什么问题。我想问题和服务器有关。在新服务器中重新部署,从零开始解决了问题。。。
/**
 * Set whether to prepare the underlying JDBC Connection of a transactional
 * Hibernate Session, that is, whether to apply a transaction-specific
 * isolation level and/or the transaction's read-only flag to the underlying
 * JDBC Connection.
 * <p>Default is "true". If you turn this flag off, the transaction manager
 * will not support per-transaction isolation levels anymore.  ...
 */
public void setPrepareConnection(boolean prepareConnection) {
    this.prepareConnection = prepareConnection;
}
if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
    ....
}
/**
 * Return whether the given Hibernate Session will always hold the same
 * JDBC Connection. This is used to check whether the transaction manager
 * can safely prepare and clean up the JDBC Connection used for a transaction.
 * <p>The default implementation checks the Session's connection release mode
 * to be "on_close".
 */
protected boolean isSameConnectionForEntireSession(Session session) ...