Spring Jdbc

    详细介绍目前为止接触到的SpringJDBC的用法。

    Mysql数据库:
Spring Jdbc_第1张图片

     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封装。


      Spring中JdbcTemplate将使用的JDBC的流程封装起来,包括了异常的捕捉、SQL的执行、查询结果的转换等等。Spring大量使用Template Method模式来封装固定流程的动作,XXXTemplate等类别都是基于这种方式的实现。 
     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);
}


你可能感兴趣的:(Spring Jdbc)