简体   繁体   中英

MyBatis Not Persisting Stored Procedure Call

I am using Spring 4 with MyBatis 3. I am calling a stored procedure in Oracle 11g which processes a bunch of data from a staging table and inserts the data into several other tables. The stored procedure calls commit inside it. However nothing is being persisted, there are no exceptions or warnings, nothing in the logs except this.

11:59:48.297 DEBUG BaseJdbcLogger.debug - ==>  Preparing: {call PKG_DIRECTORY.sp_process_staged_data} 
11:59:48.318 DEBUG BaseJdbcLogger.debug - ==> Parameters: 

Here is my definition in my mapper file

<insert id="processDirectory" statementType="CALLABLE">
    {call PKG_DIRECTORY.sp_process_staged_data}
</insert>

Here is the interface

public interface StagedDataMapper {

    @Async
    void processDirectory();

    List<StageDirectory> getStagedDirectory(long institutionId);

    List<StageAppointment> getStagedAppointment(long institutionId);
}

I've tried insert, update, select, nothing works.

UPDATE:

I found a tiny mistake however it did not correct the issue.

Updated mapper file

<select id="processDirectory" statementType="CALLABLE">
    {call PKG_DIRECTORY.sp_process_staged_data()}
</select>

I can run call PKG_DIRECTORY.sp_process_staged_data() on the database directly and it works just fine.

Update 2:

Here is my MyBatis config:

@Configuration
public class PersistenceConfig {

    @Autowired
    Environment environment;

    @Bean(name = "datasource")
    public ComboPooledDataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(environment.getRequiredProperty("c3p0.driver"));
        dataSource.setJdbcUrl(environment.getRequiredProperty("c3p0.url"));
        dataSource.setUser(environment.getRequiredProperty("c3p0.user"));
        dataSource.setPassword(environment.getRequiredProperty("c3p0.password"));
        dataSource.setInitialPoolSize(environment.getRequiredProperty("c3p0.initialPoolSize", Integer.class));
        dataSource.setMaxPoolSize(environment.getRequiredProperty("c3p0.maxPoolSize", Integer.class));
        dataSource.setMinPoolSize(environment.getRequiredProperty("c3p0.minPoolSize", Integer.class));
        dataSource.setAcquireIncrement(environment.getRequiredProperty("c3p0.acquireIncrement", Integer.class));
        dataSource.setMaxStatements(environment.getRequiredProperty("c3p0.maxStatements", Integer.class));
        dataSource.setMaxIdleTime(environment.getRequiredProperty("c3p0.maxIdleTime", Integer.class));
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage("org.something.core.domain");
        return sessionFactory.getObject();
    }

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager() throws PropertyVetoException{
        return new DataSourceTransactionManager(dataSource());
    }

}

And my mapper

<insert id="processDirectory" statementType="CALLABLE">
    {CALL PKG_DIRECTORY.SP_PROCESS_STAGED_DATA()}
</insert>

Update 3:

I made another attempt but still no luck. Thinking about ditching MyBatis this is becoming such an issue.

Changed my persistence config a bit

public class PersistenceConfig {

    @Autowired
    Environment environment;

    @Bean(name = "datasource")
    public ComboPooledDataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(environment.getRequiredProperty("c3p0.driver"));
        dataSource.setJdbcUrl(environment.getRequiredProperty("c3p0.url"));
        dataSource.setUser(environment.getRequiredProperty("c3p0.user"));
        dataSource.setPassword(environment.getRequiredProperty("c3p0.password"));
        dataSource.setInitialPoolSize(environment.getRequiredProperty("c3p0.initialPoolSize", Integer.class));
        dataSource.setMaxPoolSize(environment.getRequiredProperty("c3p0.maxPoolSize", Integer.class));
        dataSource.setMinPoolSize(environment.getRequiredProperty("c3p0.minPoolSize", Integer.class));
        dataSource.setAcquireIncrement(environment.getRequiredProperty("c3p0.acquireIncrement", Integer.class));
        dataSource.setMaxStatements(environment.getRequiredProperty("c3p0.maxStatements", Integer.class));
        dataSource.setMaxIdleTime(environment.getRequiredProperty("c3p0.maxIdleTime", Integer.class));
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage("org.something.core.domain");
        sessionFactory.setTransactionFactory(springManagedTransactionFactory());
        return sessionFactory.getObject();
    }

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager() throws PropertyVetoException{
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public SpringManagedTransactionFactory springManagedTransactionFactory() {
        return new SpringManagedTransactionFactory();
    }

}

Rolled mybatis version from 3.3.0 down to 3.2.8 and mybatis-spring from 1.2.3 down to 1.2.2.

Mapper looks like this:

public interface StagedDataMapper {

    void processDirectory();

    List<StageDirectory> getStagedDirectory(long institutionId);

    List<StageAppointment> getStagedAppointment(long institutionId);
}

Controller method

@Transactional
    @RequestMapping(value = "/directory/process", method = RequestMethod.POST)
    public ResponseEntity processStagedDirectory() {
        stagedDataMapper.processDirectory();
        return new ResponseEntity(HttpStatus.ACCEPTED);
    }

Not sure what but the following works

<insert id="processDirectory" statementType="CALLABLE">
    <![CDATA[{ CALL PKG_DIRECTORY.SP_PROCESS_STAGED_DATA() }]]>
</insert>

This does not

<insert id="processDirectory" statementType="CALLABLE">
    { CALL PKG_DIRECTORY.SP_PROCESS_STAGED_DATA() }
</insert>

MyBatis seems to rollback all query that are not explicit UPDATE or DELETE.

For me, the solution was to add the property commitRequired="true" to the . Not sure how this translate to your situation but it seems to be the same problem.

Exemple coming from LSC-Project (which use MyBatis):

  <transactionManager type="JDBC" commitRequired="true">
    <dataSource type="SIMPLE">
      <property value="${driver}" name="JDBC.Driver" />
      <property value="${url}" name="JDBC.ConnectionURL" />
      <property value="${username}" name="JDBC.Username"/>
      <property value="${password}" name="JDBC.Password"/>
      <property value="15" name="Pool.MaximumActiveConnections"/>
      <property value="15" name="Pool.MaximumIdleConnections"/>
      <property value="1000" name="Pool.MaximumWait"/>
    </dataSource>
  </transactionManager>

Quite an old question, but the obvious answer is not there. Just change

<select ... </select>;

to

<update ... </update>

This signals MyBatis to honor the transactional behaviour.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM