spring对数据库的操作使用JdbcTemplate来封装JDBC,结合Spring的注入特性可以很方便的实现对数据库的访问操作。
一、对数据库的访问操作
1、实体Bean
package com.bean;
public class Person {
private Integer id;
private String name;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.hpe.dao;
import java.util.List;
import com.service;
public interface PersonService {
/**
* 保存person
* @param person
* @return
*/
public abstract void save(Person person);
/**
* 更新person
* @param person
* @return
*/
public abstract void update(Person person);
/**
* 获取person
* @param personid
* @return
*/
public abstract Person getPerson(Integer personid);
/**
* 获取所有person
* @return
*/
public abstract List
getPersons();
/**
* 删除指定id的person
* @param personid
*/
public abstract void delete(Integer personid);
}
package com.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.Transactional;
import com.bean;
public class PersonServiceBean implements PersonService {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void save(Person person) {
String sql = "insert into person(name,del_flg) values(?,0)";
Object[] params = {person.getName()};
jdbcTemplate.update(sql, params, new int[]{java.sql.Types.VARCHAR});
}
@Override
public void update(Person person) {
String sql = "update person set name=? where id=?";
Object[] params = {person.getName(),person.getId()};
jdbcTemplate.update(sql, params, new int[]{java.sql.Types.VARCHAR,java.sql.Types.INTEGER});
}
@Override
public Person getPerson(Integer personid) {
String sql = "select * from person where id=?";
Object[] params = {personid};
return (Person)jdbcTemplate.queryForObject(sql, params, new int[]{java.sql.Types.INTEGER},new RowMapper
() {
@Override
public Person mapRow(ResultSet rs, int arg1) throws SQLException {
Person person = new Person(rs.getString("name"));
person.setId(rs.getInt("id"));
return person;
}
});
}
@Override
public List
getPersons() {
String sql = "select * from person";
return (List
)jdbcTemplate.query(sql, new RowMapper
() {
@Override
public Person mapRow(ResultSet rs, int i) throws SQLException {
Person person = new Person();
person.setName(rs.getString("name"));
person.setId(rs.getInt("id"));
return person;
}
});
}
@Override
public void delete(Integer personid) {
String sql = "update person set del_flg=1 where id=?";
Object[] params = {personid};
jdbcTemplate.update(sql, params, new int[]{java.sql.Types.INTEGER});
}
}
package com.test;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.RowCallbackHandler;
import com.service.PersonServiceBean;
import com.bean.Person;
public class test {
static ApplicationContext ac;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
ac = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Test
public void testPersonSave() {
PersonService ps = (PersonService) ac.getBean("personService");
ps.save(new Person("XXX"));
}
@Test
public void testGetPerson() {
PersonService ps = (PersonService) ac.getBean("personService");
Person p = ps.getPerson(4);
System.out.println(p.getName());
}
@Test
public void testUpdate() {
PersonService ps = (PersonService) ac.getBean("personService");
Person p = ps.getPerson(4);
p.setName("111");
ps.update(p);
}
@Test
public void testDelete() {
PersonService ps = (PersonService) ac.getBean("personService");
ps.delete(4);
}
@Test
public void testGetps() {
PersonService ps = (PersonService) ac.getBean("personService");
for(Person p:ps.getPersons()){
System.out.println(p.getName());
}
}
}
二、基本的数据操作
1.更新数据
JdbcTemplate提供了若干update()方法,允许用户对数据表记录进行添加,更新和删除操作。JdbcTemplate在内部通过PreparedStatement执行SQL语句,所以可以使用绑定参 数的SQL语句,每个占位符可接受一个参数。通过JdbcTemplate的int update(String sql, Object[] args)方法进行表数据的更新。
通过update(String sql, Object[] args)方法为SQL语句的占位符绑定参数时,并没有 显式指定对应字段的数据类型,此时,Spring直接让PreparedStatement根据参数 的类型进行“猜测”。
更好的一种做法是,使用int update(String sql, Object[] args, int[] argTypes)显式指定每个占位符所对应的字段数据类型,这样就可以保证类型安全。
除了以上两个update()方法外,JdbcTemplate还提供以下几个功能相似的重载方法。
--int update(String sql):为不带占位符的SQL语句所提供的便利方法。
--int update(String sql, PreparedStatementSetter pss): PreparedStatementSetter是一个回调接口,它定义了一个void setValues(PreparedStatement ps)接口方法。JdbcTemplate使用SQL语句创建出PreparedStatement实例后,将调用该回调 接口执行绑定参数的操作。
3.查询数据
(1)使用RowCaIIbackHandler处理结果集Spring提供了org.springframework.jdbc.core.RowCallbackHandler回调接口,通过该 接口可以定义如何从结果集中获取数据。RowCaIlbackHandler接口很简单,仅有一 个方法void processRow(ResultSet rs) throws SQLException。 Spring会遍历结果集, 对结果集中的每一行调用RowCallbackHandler回调接口处理数据。所以用户无 须 调用ResultSet的next()方法,而只需要定义好如何获取结果行数据的逻辑就可以了。
如果需要获取多条记录,依旧可以使用RowCallbackHandler完成任务,只需要稍微调整一下结果集的处理逻辑就可以了。
当结果集中没有数据时,并不会抛出异常。只是此时RowCallbackHandle:回调接口 中定义的处理逻辑没有得到调用罢了。
(2)使用RowMapper<T>处理结果集
Spring还提供了一个和RowCallbackHandler功能类似的RowMapper<T>接口,它也可以使用RowMapper<T>定义结果集映射逻辑,在结果集为多行记录时,该接口更 容易使用。RowMapper<T>也只有一个接口方法:T mapRow(ResultSet rs, int rowNum)
4.查询单值数据
如果查询的结果集仅有一个值,如SELECT COUNT(*) FROM User等,就可以使用更 简单的方式获取结果的值。JdbcTemplate为获取结果集中的单值数据提供了3组方 法,分别用于获取int, long的单值,其他类型的单值以Object类型返回。(1)int类型的单值查询方法
int queryForlnt(String sql)int queryForInt(String sql, Object... args)
int queryForInt(String sql, Object[] args, int[] argTypes)
(2)long类型的单值查询方法
long queryForLong(String sql)long queryForLong(String sql, Object... args)
long queryForLong(String sql, Object[] args, int[] argTypes)
(3)其他类型的单值查询接口
<T> T queryForObject(String sql, Class<T> requiredType)<T> T queryForObject(String sql, Object[] args, Class<T>requiredType)
<T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType)
<T> T queryForObject(String sql, Object[] args, int[] argTypes,RowMapper<T> rowMapper)
<T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper)
<T> T queryForObject(String sql, RowMapper<T> rowMapper)>
使用带Class<T> requiredType参数的方法时,结果集必须仅拥有一行一列,且结果集可以被造型成T类型的对象。如果结果集包括多列,则需要使用带RowMapper<T> rowMapper的方法,在接口方法中手工完成对象构造。
5、批量更改数据
如果需要一次性插人或更新多条记录,当然可以简单地通过多次调用update()方法完成任务,但这不是最好的实现方案。更好的选择是使用JdbcTemplate批量更改数据的方法。一般情况下,后者拥有更好的性能,因为更新的数据将被批量发送到数据库中,它减少了对数据库访问的次数。--public int[] batchUpdate(String[] sql)
多条SQL语句组成一个数组(这些SQL语句不带参数),该方法以批量方式执行这些 SQL语句。Spring在内部使用Jdbc提供的批量更新API完成操作,如果底层的Jdbc Driver不支持批量更新操作,Spring将采用逐条更新的方式模拟批量更新。
--public int[] batchUpdate(String sql, BatchPreparedStatementSetter pss)
使用本方法对于同一结构的带参SQL语句多次进行数据更新操作。通过 BatchPreparedStatementSetter回调接口进行批量参数的绑定工作。而 BatchPreparedStatementSetter又定义了两个方法。
--int getBatchSize():指定本批次的大小。
--void setValues(PreparedStatement ps, int i):为给定的PreparedStatement设置参数。