简体   繁体   English

Spring / Hibernate / HSQLDB组合的会话/事务问题

[英]Session / Transaction problems with Spring/Hibernate/HSQLDB combo

for training purposes I am currently rewriting my application to use a combination of Spring and Hibernate to access my local HSQLDB instead of just doing it via JDBC alone. 出于培训目的,我目前正在重写应用程序,以结合使用Spring和Hibernate来访问本地HSQLDB,而不仅仅是通过JDBC进行操作。

I think that I got most of it working and when I execute a few methods on my main method for testing purposes everything seems to work fine. 我认为大部分工作都可以正常进行,当我在主要方法上执行一些方法进行测试时,一切似乎都可以正常工作。 However, once I want to enable the transaction handling via @Transactional the whole thing stops working, telling me that there is no connection present. 但是,一旦我想通过@Transactional启用事务处理,整个过程就会停止工作,并告诉我没有连接存在。

I already tried a few solutions given in similar question here on stackoverflow, but none did the trick for me. 我已经尝试过一些在stackoverflow上类似问题中给出的解决方案,但是没有一个对我有用。

First of all the full stacktrace: http://pastebin.com/ACkp7Ysj 首先是完整的堆栈跟踪: http : //pastebin.com/ACkp7Ysj

And here are my classes and config files: 这是我的类和配置文件:

Datasource Config: 数据源配置:

 <?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:aop="http://www.springframework.org/schema/aop"
 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/tx 
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
 http://www.springframework.org/schema/aop 
 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

  <bean id="dataSource"
  class="org.springframework.jdbc.datasource.DriverManagerDataSource">

  <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
  <property name="url" value="jdbc:hsqldb:file:C:\\dev\\source\\productionDB\\productionDB;shutdown=true" />
  <property name="username" value="admin" />
  <property name="password" value="admin" />
  </bean>   

  <bean id="sessionFactory" 
   class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="packagesToScan" value="exercise.java.basics.storage" />

  <property name="mappingLocations">
  <list>
  <value>classpath:hibernate/Warehouse.hbm.xml</value>

  </list>
  </property>

  <property name="hibernateProperties">
     <props>
        <prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
     </props>
  </property>

 </bean>

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

 <bean id="persistenceExceptionTranslationPostProcessor" 
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

  <tx:annotation-driven transaction-manager="txManager"/>

   </beans>

DAO Config: DAO配置:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="warehouseDAO" class="exercise.java.basics.storage.WarehouseDAOImpl">
  <property name="dataSource" ref="dataSource" />
  <property name="sessionFactory" ref="sessionFactory"/>

</bean>

</beans>

Module Config: 模块配置:

 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<import resource="database/Spring-Datasource.xml" />
<import resource="warehouse/Spring-Warehouse.xml" />

</beans>

Hibernate Mapping: 休眠映射:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="exercise.java.basics.storage.WarehouseNew" table="WAREHOUSE">
    <id name="product_ID" type="integer">
        <column name="product_ID"  not-null="true"/>
        <generator class="identity" />
    </id>
    <property name="product_name" type="string">
        <column name="product_name" length="100"/>
    </property>
    <property name="product_count" type="integer">
        <column name="product_count"/>
    </property>
 </class>
 </hibernate-mapping>

DAO Pattern: DAO模式:

public interface WarehouseDAO {

public void initializeWarehouse();

public void storeProducts( final Product product, final int count );

public void removeProducts( final Product product, final int count );

public void updateStock();

}

DAO Implementation: DAO实施:

@Transactional
@Repository
public class WarehouseDAOImpl implements WarehouseDAO {

private DataSource     dataSource;

@Autowired
private SessionFactory sessionFactory;

public void setDataSource( final DataSource dataSource ) {
    this.dataSource = dataSource;
}

public void setSessionFactory( final SessionFactory sessionFactory ) {
    this.sessionFactory = sessionFactory;
}

public void initializeWarehouse() {

    String initProductsSQL = "INSERT INTO WAREHOUSE(product_name, product_count) VALUES  (?, 0)";

    Connection conn = null;

    try {

        conn = DataSourceUtils.getConnection( this.dataSource );

        Statement stmt = conn.createStatement();

        PreparedStatement ps = conn.prepareStatement( initProductsSQL );
        ps.setString( 1, String.valueOf( Product.NAIL ) );
        ps.executeUpdate();
        ps.setString( 1, String.valueOf( Product.SCREW ) );
        ps.executeUpdate();
        ps.setString( 1, String.valueOf( Product.FINALPRODUCT ) );
        ps.executeUpdate();
        ps.close();

    } catch ( SQLException e ) {
        throw new RuntimeException( e );

    } finally {
        if ( conn != null ) {
            try {
                conn.close();
            } catch ( SQLException e ) {
                e.printStackTrace();
            }
        }
    }

}

public void storeProducts( final Product product, final int count ) {

    String updateProductCountSQL = "UPDATE WAREHOUSE SET product_count = product_count + " + count
            + " WHERE product_name = '" + product + "'";

    Connection conn = null;

    try {

        conn = DataSourceUtils.getConnection( this.dataSource );

        Statement stmt = conn.createStatement();
        stmt.execute( updateProductCountSQL );
        stmt.close();

    } catch ( SQLException e ) {
        throw new RuntimeException( e );

    } finally {
        if ( conn != null ) {
            try {
                conn.close();
            } catch ( SQLException e ) {
                e.printStackTrace();
            }
        }
    }

}

public void removeProducts( final Product product, final int count ) {

    String updateProductCountSQL = "UPDATE WAREHOUSE SET product_count = product_count - " + count
            + " WHERE product_name = '" + product + "'";

    Connection conn = null;

    try {

        conn = DataSourceUtils.getConnection( this.dataSource );

        Statement stmt = conn.createStatement();
        stmt.execute( updateProductCountSQL );
        stmt.close();

    } catch ( SQLException e ) {
        throw new RuntimeException( e );

    } finally {
        if ( conn != null ) {
            try {
                conn.close();
            } catch ( SQLException e ) {
                e.printStackTrace();
            }
        }
    }

}

public void updateStock() {

    String getUpdatedStocksSQL = "SELECT * FROM WAREHOUSE WHERE product_name = ? ;";

    Connection conn = null;

    try {

        conn = DataSourceUtils.getConnection( this.dataSource );

        PreparedStatement ps = conn.prepareStatement( getUpdatedStocksSQL );

        WarehouseNew warehouse = exercise.java.basics.storage.WarehouseNew.getInstance();

        ps.setString( 1, String.valueOf( Product.NAIL ) );
        ResultSet rsNail = ps.executeQuery();
        ps.setString( 1, String.valueOf( Product.SCREW ) );
        ResultSet rsScrew = ps.executeQuery();
        ps.setString( 1, String.valueOf( Product.FINALPRODUCT ) );
        ResultSet rsFinalProduct = ps.executeQuery();

        rsNail.next();
        rsScrew.next();
        rsFinalProduct.next();

        warehouse.setNailCount( rsNail.getString( 3 ) );
        warehouse.setScrewCount( rsNail.getString( 3 ) );
        warehouse.setFinalProductCount( rsNail.getString( 3 ) );

        //Debug
        System.out.println( rsNail.getInt( 3 ) );
        System.out.println( rsScrew.getInt( 3 ) );
        System.out.println( rsFinalProduct.getInt( 3 ) );

        rsNail.close();
        rsScrew.close();
        rsFinalProduct.close();
        ps.close();

    } catch ( SQLException e ) {
        throw new RuntimeException( e );
    } finally {
        if ( conn != null ) {
            try {
                conn.close();
            } catch ( SQLException e ) {
                e.printStackTrace();
            }
        }
    }

}

public static void main( final String[] args ) {

    ApplicationContext context = new ClassPathXmlApplicationContext( "Spring-Module.xml" );

    WarehouseDAO warehouseDAO = (WarehouseDAO) context.getBean( "warehouseDAO" );

    // warehouseDAO.initializeWarehouse();
    warehouseDAO.updateStock();

    warehouseDAO.storeProducts( Product.NAIL, 10 );
    warehouseDAO.storeProducts( Product.SCREW, 20 );
    warehouseDAO.storeProducts( Product.FINALPRODUCT, 30 );

    warehouseDAO.updateStock();

}
}

Model class: 型号类别:

public class WarehouseNew {

private int                          nailCount;
private int                          screwCount;
private int                          finalProductCount;
private int                          product_ID;

private String                       product_name;
private int                          product_count;

private static volatile WarehouseNew instance = null;

public static WarehouseNew getInstance() {
    if ( instance == null ) {
        synchronized ( WarehouseNew.class ) {
            if ( instance == null ) {
                instance = new WarehouseNew();
            }
        }
    }

    return instance;
}

/**
 * Constructor for ...
 */
private WarehouseNew() {

}

/**
 * @return the nailCount
 */
public int getNailCount() {
    return this.nailCount;
}

/**
 * @param string the nailCount to set
 */
public void setNailCount( final String string ) {
    this.nailCount = Integer.parseInt( string );
}

/**
 * @return the screwCount
 */
public int getScrewCount() {
    return this.screwCount;
}

/**
 * @param string the screwCount to set
 */
public void setScrewCount( final String string ) {
    this.screwCount = Integer.parseInt( string );
}

/**
 * @return the finalProductCount
 */
public int getFinalProductCount() {
    return this.finalProductCount;
}

/**
 * @param string the finalProductCount to set
 */
public void setFinalProductCount( final String string ) {
    this.finalProductCount = Integer.parseInt( string );
}

/**
 * @return the product_id
 */
public int getProduct_ID() {
    return this.product_ID;
}

/**
 * @param product_id the product_id to set
 */
public void setProduct_ID( final int product_ID ) {
    this.product_ID = product_ID;
}

/**
 * @return the product_name
 */
public String getProduct_name() {
    return this.product_name;
}

/**
 * @param product_name the product_name to set
 */
public void setProduct_name( final String product_name ) {
    this.product_name = product_name;
}

/**
 * @return the product_count
 */
public int getProduct_count() {
    return this.product_count;
}

/**
 * @param product_count the product_count to set
 */
public void setProduct_count( final int product_count ) {
    this.product_count = product_count;
}

}

I hope someone can point me in the right direction. 我希望有人能指出我正确的方向。 Spring framework and Hibernate are totally new to me and I just want it to work. Spring框架和Hibernate对我来说是全新的,我只是希望它能工作。

I don't really understand why the database access works when I am not using the @Transactional annonation, but then says that there is no connection present when using it... Just makes no sense to me. 我不真正理解为什么不使用@Transactional注释时数据库访问有效,但是然后说使用它时不存在连接……对我来说毫无意义。

best regards daZza 最好的问候daZza

EDIT: Changes based on the suggestion to use the sessionFactory. 编辑:基于使用sessionFactory的建议的更改。 The error remains the same though. 该错误仍然相同。

// Experimental

    this.sessionFactory.getCurrentSession().doWork(

    new Work() {
        public void execute( final Connection connection ) throws SQLException {
            try {

                String getUpdatedStocksSQL = "SELECT * FROM WAREHOUSE WHERE product_name = ? ;";

                PreparedStatement ps = connection.prepareStatement( getUpdatedStocksSQL );

                WarehouseNew warehouse = exercise.java.basics.storage.WarehouseNew.getInstance();

                ps.setString( 1, String.valueOf( Product.NAIL ) );
                ResultSet rsNail = ps.executeQuery();
                ps.setString( 1, String.valueOf( Product.SCREW ) );
                ResultSet rsScrew = ps.executeQuery();
                ps.setString( 1, String.valueOf( Product.FINALPRODUCT ) );
                ResultSet rsFinalProduct = ps.executeQuery();

                rsNail.next();
                rsScrew.next();
                rsFinalProduct.next();


                warehouse.setNailCount( rsNail.getString( 3 ) );
                warehouse.setScrewCount( rsNail.getString( 3 ) );
                warehouse.setFinalProductCount( rsNail.getString( 3 ) );

                System.out.println( rsNail.getInt( 3 ) );
                System.out.println( rsScrew.getInt( 3 ) );
                System.out.println( rsFinalProduct.getInt( 3 ) );

                rsNail.close();
                rsScrew.close();
                rsFinalProduct.close();
                ps.close();

            } catch ( SQLException e ) {
                throw new RuntimeException( e );
            } finally {
                if ( connection != null ) {
                    try {
                        connection.close();
                    } catch ( SQLException e ) {
                        e.printStackTrace();
                    }
                }
            }
        }
    } );

    // !Experimental

I think that your jdbc driver URL is incorrect: 我认为您的jdbc驱动程序URL不正确:

for HSQL it's 对于HSQL

org.hsqldb.jdbcDriver

you seem to have 你似乎有

<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />

which is a MS-SQL/Sybase driver class. 这是MS-SQL / Sybase驱动程序类。

The main reason why your @Transaction annotation is failing at this point is that you are using a hibernate transaction manager (and would therefore only work when you start using the session factory). 此时@Transaction注释失败的主要原因是您使用的是休眠事务管理器(因此,只有在开始使用会话工厂时才起作用)。

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

For your old jdbc code to work you need to have something like this in place instead: 为了使旧的jdbc代码正常工作,您需要使用以下代码:

<bean id="txManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

An alternative way is to replace your DataSourceUtils.getConnection( this.dataSource with sessionFactory.getCurrentSession().connection(). This is actually deprectated so you'd be better off using sessionFactory.getCurrentSession.doWork() instead. 另一种方法是用sessionFactory.getCurrentSession()。connection()替换您的DataSourceUtils.getConnection(this.dataSource。)实际上取消,因此最好使用sessionFactory.getCurrentSession.doWork()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Hibernate 和 Spring3 事务管理注释-配置问题:休眠异常:没有 Hibernate Session 绑定到线程 - Hibernate and Spring3 Transaction Management Annotation-Configuration problems: Hibernate-Exception: No Hibernate Session bound to thread 由春季交易经理管理的“暂停”休眠会话 - “suspend” hibernate session managed by spring transaction manager Spring/Hibernate/TestNG - 手动 session 和事务设置 - Spring/Hibernate/TestNG - manual session and transaction setup org.hibernate.LazyInitializationException:无法初始化代理-没有会话。 Spring + Hibernate + HSQLDB - org.hibernate.LazyInitializationException: could not initialize proxy - no Session. Spring + Hibernate + HSQLDB 参照Spring-Hibernate的“事务同步会话”是什么意思? - What does it mean by “Transaction Synchronized Session” with reference to Spring-Hibernate? 无法为事务 JAVA MAVEN SPRING 打开 Hibernate 会话 - Could not open Hibernate Session for transaction JAVA MAVEN SPRING 事务回滚后,Spring不会关闭hibernate会话 - Spring doesn't close hibernate session after transaction rollback 使用Spring 3和Hibernate 4在Open-Session-In-View中实现注释驱动事务 - Implementation of Annotation Driven Transaction in Open-Session-In-View with Spring 3 and Hibernate 4 执行休眠Interceptor后,它通过Spring事务关闭会话管理 - After executing hibernate Interceptor it close session manage by spring transaction 在Spring中使用JPA EntityManager和Hibernate会话与共享事务管理器 - Using both JPA EntityManager and Hibernate session with shared transaction manager in Spring
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM