编程式事务管理方法允许你在对你的源代码编程的帮助下管理事务。这给了你极大地灵活性,但是它很难维护。
在我们开始之前,至少要有两个数据库表,在事务的帮助下我们可以执行多种 crud 操作。以 student 表为例,用下述 ddl 可以在 mysql test 数据库中创建该表:
create table student(
id int not null auto_increment,
name varchar(20) not null,
age int not null,
primary key (id)
);
第二个表是 marks,用来存储基于年份的学生的标记。这里 sid 是 student 表的外键。
create table marks(
sid int not null,
marks int not null,
year int not null
);
让我们直接使用 platformtransactionmanager 来实现编程式方法从而实现事务。要开始一个新事务,你需要有一个带有适当的 transaction 属性的 transactiondefinition 的实例。这个例子中,我们使用默认的 transaction 属性简单的创建了 defaulttransactiondefinition 的一个实例。
当 transactiondefinition 创建后,你可以通过调用 gettransaction() 方法来开始你的事务,该方法会返回 transactionstatus 的一个实例。 transactionstatus 对象帮助追踪当前的事务状态,并且最终,如果一切运行顺利,你可以使用 platformtransactionmanager 的 commit() 方法来提交这个事务,否则的话,你可以使用 rollback() 方法来回滚整个操作。
现在让我们编写我们的 spring jdbc 应用程序,它能够在 student 和 mark 表中实现简单的操作。让我们适当的使用 eclipse ide,并按照如下所示的步骤来创建一个 spring 应用程序:
步骤 | 描述 |
---|---|
1 | 创建一个名为 springexample 的项目,并在创建的项目中的 src 文件夹下创建包 com.tutorialspoint 。 |
2 | 使用 add external jars 选项添加必需的 spring 库,解释见 spring hello world example chapter. |
3 | 在项目中添加 spring jdbc 指定的最新的库 mysql-connector-java.jar,org.springframework.jdbc.jar 和 org.springframework.transaction.jar。如果你还没有这些库,你可以下载它们。 |
4 | 创建 dao 接口 studentdao 并列出所有需要的方法。尽管它不是必需的并且你可以直接编写 studentjdbctemplate 类,但是作为一个好的实践,我们还是做吧。 |
5 | 在 com.tutorialspoint 包下创建其他必需的 java 类 studentmarks,studentmarksmapper,studentjdbctemplate 和 mainapp。如果需要的话,你可以创建其他的 pojo 类。 |
6 | 确保你已经在 test 数据库中创建了 student 和 marks 表。还要确保你的 mysql 服务器运行正常并且你使用给出的用户名和密码可以读/写访问数据库。 |
7 | 在 src 文件夹下创建 beans 配置文件 beans.xml 。 |
8 | 最后一步是创建所有 java 文件和 bean 配置文件的内容并按照如下所示的方法运行应用程序。 |
下面是数据访问对象接口文件 studentdao.java 的内容:
package com.tutorialspoint;
import java.util.list;
import javax.sql.datasource;
public interface studentdao {
/**
* this is the method to be used to initialize
* database resources ie. connection.
*/
public void setdatasource(datasource ds);
/**
* this is the method to be used to create
* a record in the student and marks tables.
*/
public void create(string name, integer age, integer marks, integer year);
/**
* this is the method to be used to list down
* all the records from the student and marks tables.
*/
public list<studentmarks> liststudents();
}
下面是 studentmarks.java 文件的内容:
package com.tutorialspoint;
public class studentmarks {
private integer age;
private string name;
private integer id;
private integer marks;
private integer year;
private integer sid;
public void setage(integer age) {
this.age = age;
}
public integer getage() {
return age;
}
public void setname(string name) {
this.name = name;
}
public string getname() {
return name;
}
public void setid(integer id) {
this.id = id;
}
public integer getid() {
return id;
}
public void setmarks(integer marks) {
this.marks = marks;
}
public integer getmarks() {
return marks;
}
public void setyear(integer year) {
this.year = year;
}
public integer getyear() {
return year;
}
public void setsid(integer sid) {
this.sid = sid;
}
public integer getsid() {
return sid;
}
}
以下是 studentmarksmapper.java 文件的内容:
package com.tutorialspoint;
import java.sql.resultset;
import java.sql.sqlexception;
import org.springframework.jdbc.core.rowmapper;
public class studentmarksmapper implements rowmapper<studentmarks> {
public studentmarks maprow(resultset rs, int rownum) throws sqlexception {
studentmarks studentmarks = new studentmarks();
studentmarks.setid(rs.getint("id"));
studentmarks.setname(rs.getstring("name"));
studentmarks.setage(rs.getint("age"));
studentmarks.setsid(rs.getint("sid"));
studentmarks.setmarks(rs.getint("marks"));
studentmarks.setyear(rs.getint("year"));
return studentmarks;
}
}
下面是定义的 dao 接口 studentdao 实现类文件 studentjdbctemplate.java:
package com.tutorialspoint;
import java.util.list;
import javax.sql.datasource;
import org.springframework.dao.dataaccessexception;
import org.springframework.jdbc.core.jdbctemplate;
import org.springframework.transaction.platformtransactionmanager;
import org.springframework.transaction.transactiondefinition;
import org.springframework.transaction.transactionstatus;
import org.springframework.transaction.support.defaulttransactiondefinition;
public class studentjdbctemplate implements studentdao {
private datasource datasource;
private jdbctemplate jdbctemplateobject;
private platformtransactionmanager transactionmanager;
public void setdatasource(datasource datasource) {
this.datasource = datasource;
this.jdbctemplateobject = new jdbctemplate(datasource);
}
public void settransactionmanager(
platformtransactionmanager transactionmanager) {
this.transactionmanager = transactionmanager;
}
public void create(string name, integer age, integer marks, integer year){
transactiondefinition def = new defaulttransactiondefinition();
transactionstatus status = transactionmanager.gettransaction(def);
try {
string sql1 = "insert into student (name, age) values (?, ?)";
jdbctemplateobject.update( sql1, name, age);
// get the latest student id to be used in marks table
string sql2 = "select max(id) from student";
int sid = jdbctemplateobject.queryforint( sql2 );
string sql3 = "insert into marks(sid, marks, year) " +
"values (?, ?, ?)";
jdbctemplateobject.update( sql3, sid, marks, year);
system.out.println("created name = " + name + ", age = " + age);
transactionmanager.commit(status);
} catch (dataaccessexception e) {
system.out.println("error in creating record, rolling back");
transactionmanager.rollback(status);
throw e;
}
return;
}
public list<studentmarks> liststudents() {
string sql = "select * from student, marks where student.id=marks.sid";
list <studentmarks> studentmarks = jdbctemplateobject.query(sql,
new studentmarksmapper());
return studentmarks;
}
}
现在让我们改变主应用程序文件 mainapp.java,如下所示:
package com.tutorialspoint;
import java.util.list;
import org.springframework.context.applicationcontext;
import org.springframework.context.support.classpathxmlapplicationcontext;
import com.tutorialspoint.studentjdbctemplate;
public class mainapp {
public static void main(string[] args) {
applicationcontext context =
new classpathxmlapplicationcontext("beans.xml");
studentjdbctemplate studentjdbctemplate =
(studentjdbctemplate)context.getbean("studentjdbctemplate");
system.out.println("------records creation--------" );
studentjdbctemplate.create("zara", 11, 99, 2010);
studentjdbctemplate.create("nuha", 20, 97, 2010);
studentjdbctemplate.create("ayan", 25, 100, 2011);
system.out.println("------listing all the records--------" );
list<studentmarks> studentmarks = studentjdbctemplate.liststudents();
for (studentmarks record : studentmarks) {
system.out.print("id : " + record.getid() );
system.out.print(", name : " + record.getname() );
system.out.print(", marks : " + record.getmarks());
system.out.print(", year : " + record.getyear());
system.out.println(", age : " + record.getage());
}
}
}
下面是配置文件 beans.xml 的内容:
<?xml version="1.0" encoding="utf-8"?>
<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-3.0.xsd ">
<!-- initialization for data source -->
<bean id="datasource"
class="org.springframework.jdbc.datasource.drivermanagerdatasource">
<property name="driverclassname" value="com.mysql.jdbc.driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<!-- initialization for transactionmanager -->
<bean id="transactionmanager"
class="org.springframework.jdbc.datasource.datasourcetransactionmanager">
<property name="datasource" ref="datasource" />
</bean>
<!-- definition for studentjdbctemplate bean -->
<bean id="studentjdbctemplate"
class="com.tutorialspoint.studentjdbctemplate">
<property name="datasource" ref="datasource" />
<property name="transactionmanager" ref="transactionmanager" />
</bean>
</beans>
当你完成了创建源和 bean 配置文件后,让我们运行应用程序。如果你的应用程序运行顺利的话,那么将会输出如下所示的消息:
------records creation--------
created name = zara, age = 11
created name = nuha, age = 20
created name = ayan, age = 25
------listing all the records--------
id : 1, name : zara, marks : 99, year : 2010, age : 11
id : 2, name : nuha, marks : 97, year : 2010, age : 20
id : 3, name : ayan, marks : 100, year : 2011, age : 25