详细介绍目前为止接触到的SpringJDBC的用法。
Mysql数据库:

applicationContext.xml
实体类User
最基本的MysqlJdbc
JdbcTemplate的使用示例:
如果String sql = "select * from user where name = ?",对应的有多条结果,那么queryForObject会报错。这时需要用query
测试示例:
Mysql数据库:
applicationContext.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-2.5.xsd">
<bean id="mysqlJdbc" class="com.zero.MysqlJdbc">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="mysqlJdbcTemplate" class="com.zero.MysqlJdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="mysqlNamedParameterJdbcTemplate" class="com.zero.MysqlNamedParameterJdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="mysqlJdbcDaoSupport" class="com.zero.MysqlJdbcDaoSupport">
<property name="dataSource" ref="dataSource"></property>
</bean>
<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/zero" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
</beans>
实体类User
public class User {
private int id;
private String name;
private String password;
private Date createTime;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
最基本的MysqlJdbc
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.sql.DataSource;
public class MysqlJdbc {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insert(User u) {
String sql = "insert into user (name, password, createTime) values(?, ?, ?)";//普通的sql语句
Connection conn = null;
try {
conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, u.getName());
ps.setString(2, u.getPassword());
ps.setDate(3, new Date(u.getCreateTime().getTime()));
ps.executeUpdate();
ps.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
}
可以看出来这是最基本的操作,需要手动获取连接和关闭连接,没有被Spring封装。
JdbcTemplate的使用示例:
import java.sql.Types;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameterValue;
public class MysqlJdbcTemplate {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insert1(User u) {
String sql = "insert into user (name, password, createTime) values(?, ?, ?)";// 普通的sql语句
JdbcTemplate template = new JdbcTemplate(dataSource);
template.update(sql,
new Object[] { u.getName(), u.getPassword(), u.getCreateTime() });
}
public void insert2(User u) {
String sql = "insert into user (name, password, createTime) values(?, ?, ?)";// 普通的sql语句
JdbcTemplate template = new JdbcTemplate(dataSource);
template.update(sql, new SqlParameterValue(Types.VARCHAR, u.getName()),
new SqlParameterValue(Types.VARCHAR, u.getPassword()),
new SqlParameterValue(Types.DATE, u.getCreateTime()));
}
}
相较与之前的代码操作,JdbcTemplate简洁方便。
NamedParameterJdbcTemplate是对JdbcTemplate进行了封装,主要多了一层对参数的解析,sql使用特殊组合的占位符,参数主要使用map,这样sql的占位符和参数数据就不需要在顺序上一一进行对应。
NamedParameterJdbcTemplate使用示例:import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
public class MysqlNamedParameterJdbcTemplate {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insert(User u) {
String sql = "insert into user(name, password, createTime) values (:name, :password, :createTime) ";
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(
dataSource);
SqlParameterSource ps = new BeanPropertySqlParameterSource(u);
KeyHolder keyHolder = new GeneratedKeyHolder();
namedParameterJdbcTemplate.update(sql, ps, keyHolder);
u.setId(keyHolder.getKey().intValue());
}
}
SqlParameterSource ps = new BeanPropertySqlParameterSource(user);可以使用SqlParameterSource来传递一个对象,来对sql的占位符进行填值, KeyHolder keyHolder = new GeneratedKeyHolder();来捕获生成的主键值。
JdbcDaoSupport封装了JdbcTemplate,最常使用。(SimpleJdbcTemplate即封装了JdbcTemplate,封装了NamedParameterJdbcTemplate,但是Spring4.1.2中已经不推荐使用)
JdbcDaoSupport使用示例:import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Map;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
public class MysqlJdbcDaoSupport extends JdbcDaoSupport {
// JdbcDaoSupport类已经有了public final void setDataSource(DataSource
// dataSource)了
// 不用重写也不能重写
public void insert(User u) {
String sql = "insert into user (name, password, createTime) values(?, ?, ?)";// 普通的sql语句
this.getJdbcTemplate()
.update(sql,
new Object[] { u.getName(), u.getPassword(),
u.getCreateTime() });
}
public void insertAndGetKey(final User u) {
final String sql = "insert into user (name, password, createTime) values(?, ?, ?)";// 普通的sql语句
// 获取插入数据的主键
// 使用update(PreparedStatementCreator, KeyHolder)
KeyHolder keyHolder = new GeneratedKeyHolder();
this.getJdbcTemplate().update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con)
throws SQLException {
// TODO Auto-generated method stub
PreparedStatement preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1, u.getName());
preparedStatement.setString(2, u.getPassword());
preparedStatement.setDate(3, new Date(u.getCreateTime()
.getTime()));
return preparedStatement;
}
}, keyHolder);
Map map = keyHolder.getKeys();
System.out.println(map);// {GENERATED_KEY=10}
//获取主键值
u.setId(keyHolder.getKey().intValue());
System.out.println(u.getId());// 10
}
}
从代码上来看,获取主键值时NamedParameterJdbcTemplate要比JdbcTemplate更方便,可以实现自己的DaoSupport extends JdbcDaoSupport,并把NamedParameterJdbcTemplate封装进去。
从上面的例子可以知道关于JdbcTemplate使用时两种传参方式,new Object[]{}与new SqlParameterValue(),还可以使用new PreparedStatementSetter()。
public void insert2(final User u) {
String sql = "insert into user (name, password, createTime) values(?, ?, ?)";// 普通的sql语句
this.getJdbcTemplate().update(sql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, u.getName());
ps.setString(2, u.getPassword());
ps.setDate(3, new Date(u.getCreateTime().getTime()));
}
});
}
查询操作:
public User getUserById(int id) {
try {
String sql = "select * from user where id = ?";
User user = this.getJdbcTemplate().queryForObject(sql,
new BeanPropertyRowMapper(User.class),
new SqlParameterValue(Types.INTEGER, 1));
return user;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
这里new BeanPropertyRowMapper(User.class)实际上是将User包装成了RowMapper<User>。否则需要自己对User进行包装。如下:import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import org.springframework.jdbc.core.RowMapper;
public class User implements RowMapper<User>{
private int id;
private String name;
private String password;
private Date createTime;
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setCreateTime(rs.getDate("createTime"));
return user;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
User必须 implements RowMapper<User>,并实现User mapRow(ResultSet rs, int rowNum)方法。可以看出,User必须要有空的构造函数,否则报错。如果String sql = "select * from user where name = ?",对应的有多条结果,那么queryForObject会报错。这时需要用query
public List<User> getUserByName(String name) {
try {
String sql = "select * from user where name = ?";
List<User> user = this.getJdbcTemplate().query(sql,
new BeanPropertyRowMapper(User.class),
new SqlParameterValue(Types.VARCHAR, name));
return user;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
迭代器模式list.iterator()方法获取数据:
public void getData(String name) {
String sql = "select * from user where name = '" + name+"'";
System.out.println(sql);
try {
List rows = this.getJdbcTemplate().queryForList(sql);
Iterator it = rows.iterator();
while(it.hasNext()) {
Map map = (Map) it.next();
System.out.println(map);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
运行结果:select * from user where name = '印'
{id=7, name=印, password=123456, createTime=2015-06-16}
{id=8, name=印, password=123456, createTime=2015-06-16}
{id=9, name=印, password=123456, createTime=2015-06-16}
{id=10, name=印, password=123456, createTime=2015-06-16}
{id=12, name=印, password=123456, createTime=2015-06-16}
查询某一行或记录:
String sql = "select name from user where id = 4";
String str = this.getJdbcTemplate().queryForObject(sql, String.class);
System.out.println(str);
String sql = "select count(*) from user";
Integer integer = this.getJdbcTemplate().queryForObject(sql, Integer.class);
System.out.println(integer);
同时查询两行记录,比如把id和name字段合并成id_name格式的结果:
String sql = "select id, name from user";
List<String> list = this.getJdbcTemplate().query(sql, new RowMapper<String>(){
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
String string = rs.getInt("id")+"_"+rs.getString("name");
return string;
}
});
System.out.println(list);
事务操作:
public String doInConnection(Connection conn) throws SQLException,
DataAccessException {
try {
conn.setAutoCommit(false);//关闭自动提交
String sql1 = "..... ";
PreparedStatement ps = conn.prepareStatement(sql1);
ps.executeUpdate();
String sql2 = "....";
PreparedStatement pStatement = conn.prepareStatement(sql2);
pStatement.executeUpdate();
conn.commit();
} catch (SQLException e) {
if (conn != null)
conn.rollback();//回滚
}finally{
conn.setAutoCommit(true);//开启自动提交
}
return null;
}
});
测试示例:
@Test
public void testMysqlJdbc() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MysqlJdbc mysqlJdbc = (MysqlJdbc) ctx.getBean("mysqlJdbc");
User user = new User();
user.setName("zero");
user.setPassword("123456");
user.setCreateTime(new Date());
mysqlJdbc.insert(user);
}