我正在尝试在数据库中创建两个表(ABC,XYZ)。XYZ 语法故意具有错误的语法,并且假定会失败。这个想法是在尝试 XYZ 时应该回滚 ABC 的表创建。我是 Spring Transaction 的新手,并且四处搜索以提出这个简单的示例,日志似乎显示 TransactionManager 正在回滚,但最后我看到表 ABC 存在于数据库中。谁能解释为什么@Transactional 没有在这里回滚...
package com.tango.db.dao;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
public class DBDAO {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Transactional(rollbackFor = Exception.class)
public void createTables(){
jdbcTemplate.execute("CREATE TABLE ABC(ID NUMBER NOT NULL, NAME VARCHAR2(35), primary key(ID))");
jdbcTemplate.execute("CREATE TABLE XYZ(ID NUMBER NOT NULL, NAME VARCHAR2(35), UPDATE DATE(7), primary key(ID))");
}
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
DBDAO dbdao = (DBDAO)ctx.getBean("dbDAO");
dbdao.createTables();
}
}
弹簧上下文.xml
<bean id="local.oracle.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:@10.211.55.6:1521:xe"/>
<property name="username" value="abc"/>
<property name="password" value="1234"/>
<property name="defaultAutoCommit" value="false"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="local.oracle.dataSource"/>
</bean>
<bean id="dbDAO" class="com.tango.db.dao.DBDAO">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="local.oracle.dataSource"/>
</bean>
以下是日志:
DEBUG SQLErrorCodeSQLExceptionTranslator - Translating SQLException with SQL state '42000', error code '904', message [ORA-00904: : invalid identifier
]; SQL was [CREATE TABLE XYZ(ID NUMBER NOT NULL, NAME VARCHAR2(35), UPDATE DATE(7), primary key(ID))] for task [StatementCallback]
DEBUG DataSourceTransactionManager - Initiating transaction rollback
DEBUG DataSourceTransactionManager - Rolling back JDBC transaction on Connection [jdbc:oracle:thin:@10.211.55.6:1521:xe, UserName=DBO, Oracle JDBC driver]
DEBUG DataSourceTransactionManager - Releasing JDBC Connection [jdbc:oracle:thin:@10.211.55.6:1521:xe, UserName=DBO, Oracle JDBC driver] after transaction
DEBUG DataSourceUtils - Returning JDBC Connection to DataSource
Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [CREATE TABLE XYZ(ID NUMBER NOT NULL, NAME VARCHAR2(35), UPDATE DATE(7), primary key(ID))]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00904: : invalid identifier
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:233)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:407)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:428)
at com.tango.db.dao.DBDAO.createTables(DBDAO.java:19)
at com.tango.db.dao.DBDAO$$FastClassByCGLIB$$112527a.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at com.tango.db.dao.DBDAO$$EnhancerByCGLIB$$7b0ac5f7.createTables(<generated>)
at com.tango.db.dao.DBDAO.main(DBDAO.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: : invalid identifier
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:193)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:999)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1890)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1855)
at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:304)
at org.apache.commons.dbcp.DelegatingStatement.execute(DelegatingStatement.java:264)
at org.apache.commons.dbcp.DelegatingStatement.execute(DelegatingStatement.java:264)
at org.springframework.jdbc.core.JdbcTemplate$1ExecuteStatementCallback.doInStatement(JdbcTemplate.java:421)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:396)
... 16 more