Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.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
Java 如何在Spring中对两个查询使用相同的连接?_Java_Mysql_Database_Spring_Jdbc - Fatal编程技术网

Java 如何在Spring中对两个查询使用相同的连接?

Java 如何在Spring中对两个查询使用相同的连接?,java,mysql,database,spring,jdbc,Java,Mysql,Database,Spring,Jdbc,我在基于Spring JdbcTemplate的dao中有以下代码- getJdbcTemplate().update("Record Insert Query..."); int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()"); 问题是,有时使用连接池中的不同连接执行my update和queryForInt查询 这会导致返回不正确的recordId,因为MySql last_insert_id()应该是

我在基于Spring JdbcTemplate的dao中有以下代码-

getJdbcTemplate().update("Record Insert Query...");
int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()");
问题是,有时使用连接池中的不同连接执行my update和queryForInt查询

这会导致返回不正确的recordId,因为MySql last_insert_id()应该是从发出insert查询的同一个连接调用的

我考虑过SingleConnectionDataSource,但不想使用它,因为它会降低应用程序的性能。对于这两个查询,我只需要一个连接。并非针对所有服务的所有请求

所以我有两个问题:

  • 我可以管理模板类使用的连接吗
  • JdbcTemplate是否执行自动事务管理?如果我手动将事务应用于Dao方法,这是否意味着每个查询将创建两个事务
  • 希望你们能对这个话题有所启发

    更新-我尝试了nwinkler的方法,并将我的服务层包装在一个事务中。我很惊讶地看到同样的错误在某个时候再次出现。深入研究Spring源代码,我发现了这个-

    public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) 
    throws DataAccessException {
    //Lots of code  
    Connection con = DataSourceUtils.getConnection(getDataSource()); 
    //Lots of code 
    }
    
    public T执行(PreparedStatementCreator psc,PreparedStatementCallback操作)
    抛出DataAccessException{
    //很多代码
    Connection con=DataSourceUtils.getConnection(getDataSource());
    //很多代码
    }
    
    因此,与我的想法相反,每个事务不一定有一个数据库连接,而是每个执行的查询都有一个连接。 这让我回到我的问题上来。我想从同一个连接执行两个查询:-(

    更新-

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName" value="${db.driver}" />
            <property name="url" value="${db.jdbc.url}" />
            <property name="username" value="${db.user}" />
            <property name="password" value="${db.password}" />
            <property name="maxActive" value="${db.max.active}" />
            <property name="initialSize" value="20" />
        </bean>
    
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
            autowire="byName">
            <property name="dataSource">
                <ref local="dataSource" />
            </property>
        </bean>
    
    
        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" timeout="30" />
            </tx:attributes>
        </tx:advice>
        <aop:config>
            <aop:pointcut id="pointcut" expression="execution(* service.*.*(..))" />
            <aop:pointcut id="pointcut2" expression="execution(* *.ws.*.*(..))" />
    
            <aop:advisor pointcut-ref="pointcut" advice-ref="transactionAdvice" />
            <aop:advisor pointcut-ref="pointcut2" advice-ref="transactionAdvice" />
        </aop:config>
    

    确保您的DAO包装在事务中(例如,通过使用Spring的事务拦截器)。然后,相同的连接将用于两个调用

    更好的做法是在服务层将事务提高一个级别

    文件:

    更新: 如果查看更新中引用的
    DataSourceUtils.getConnection()
    方法的JavaDoc,您将看到它获得与当前线程关联的连接:

    例如,知道绑定到当前线程的相应连接 使用{@link DataSourceTransactionManager}时,将绑定到 如果事务同步处于活动状态(例如在 {@link org.springframework.transaction.jta.JtaTransactionManager jta}事务)

    根据这一点,它应该像您设置的那样工作。我已经多次使用这种模式,从未遇到过您描述的任何问题


    也请看一下这个帖子,有人在那里处理类似的问题:

    这是我的方法:

    namedJdbcTemplate.execute(savedQuery, map, new PreparedStatementCallback<Object>() {
                @Override
                public Object doInPreparedStatement(PreparedStatement paramPreparedStatement)
                        throws SQLException, DataAccessException {
                    paramPreparedStatement.execute("SET @userLogin = 'blabla123'");
                    paramPreparedStatement.executeUpdate();
                    return null;
                }
            });
    
    namedJdbcTemplate.execute(savedQuery,map,new PreparedStatementCallback()){
    @凌驾
    公共对象doInPreparedStatement(PreparedStatement参数PreparedStatement)
    抛出SQLException、DataAccessException{
    paramPreparedStatement.execute(“SET@userLogin='blablabla123'”);
    paramPreparedStatement.executeUpdate();
    返回null;
    }
    });
    
    这没有任何并发问题,是吗?服务的多次调用仍将使用不同的事务,从而使用不同的连接。对吗?没错,这就是在服务层使用事务划分的要点。每个服务调用将在其自己的事务中运行,并将使用专用的数据库连接。提交或回滚事务后,连接将返回到池中,并可在下一个事务中使用。非常感谢。帮我省去了很多文档:-)嗯,那我猜你还是做错了什么。您可以发布您的Spring配置,包括数据源和事务管理吗?Spring代码段来自哪个类?你在哪里找到的?代码来自JdbcTemplate类。每次执行查询时都会调用它,因此我对此表示怀疑。请查看我的更新答案。。。