四、Spring的数据库访问
1、DAO模式
1 /** 2 * 抽取的一个类 3 * @author zhy 4 * 5 */ 6 public class JdbcDaoSupport { 7 8 private QueryRunner qr = new QueryRunner(DBCPUtil.getDataSource()); 9 10 public int update(String sql,Object...params){ 11 try{ 12 return qr.update(sql,params); 13 }catch(Exception e){ 14 throw new RuntimeException(e); 15 } 16 } 17 18 public <T> T query(String sql,ResultSetHandler<T> rsh,Object...params){ 19 try{ 20 return qr.query(sql,rsh,params); 21 }catch(Exception e){ 22 throw new RuntimeException(e); 23 } 24 } 25 }
1 /** 2 * 前提:不考虑事务问题。因为有AOP的存在,我们可以把事务配置起来 3 * @author zhy 4 * 5 */ 6 public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao { 7 8 public Account findAccountByName(String sourceName) { 9 return query("select * from account where name = ? ",new BeanHandler<Account>(Account.class),sourceName); 10 } 11 12 13 public void updateAccount(Account sourceAccount) { 14 update("update account set name=?,money=? where id=? ",sourceAccount.getName(),sourceAccount.getMoney(),sourceAccount.getId()) ; 15 } 16 17 }
2、Spring提供的数据库访问的模板工具类
2.1、JDBC环境搭建
2.1.1、拷贝jar包
数据库驱动
spring-jdbc-3.2.0.RELEASE.jar:访问JDBC的一个非常基本jar包
spring-orm-3.2.0.RELEASE.jar:通过ORM框架(Hibernate、MyBatis)支持jar包
spring-tx-3.2.0.RELEASE.jar:事务有关的支持jar包(如果使用的JDBC,数据库自动提交事务的前提下,此包不是必须的)
2.1.2、JdbcTemplate的基本使用
JdbcTemplate:用于直接通过JDBC访问数据用的
HibernateTemplate:用于通过Hibernate框架访问数据库用的
a、初级版本,硬编码问题
1 public class JdbcTemplateDemo1 { 2 3 public static void main(String[] args) throws DataAccessException { 4 //spring中提供了一个内置的数据源:该数据源没有性能问题,可以使用 5 DriverManagerDataSource ds = new DriverManagerDataSource(); 6 //给数据源提供必需的参数 7 ds.setDriverClassName("com.mysql.jdbc.Driver"); 8 ds.setUrl("jdbc:mysql://localhost:3306/ee0413_spring_day36"); 9 ds.setUsername("root"); 10 ds.setPassword("1234"); 11 //创建一个新的springjdbc模板 12 JdbcTemplate jt = new JdbcTemplate(); 13 //给模板赋值数据源 14 jt.setDataSource(ds); 15 jt.execute("insert into account(name,money)values('ddd',1000)"); 16 } 17 18 }
b、改进版
1 <!-- 配置一个JdbcTemplate的bean --> 2 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 3 <property name="dataSource" ref="driverManagerDataSource"></property> 4 </bean>
1 public class JdbcTemplateDemo2 { 2 3 public static void main(String[] args) throws DataAccessException { 4 //加载Spring配置文件,创建spring容器 5 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); 6 //根据id获取jdbc模板 7 JdbcTemplate jt = (JdbcTemplate)ac.getBean("jdbcTemplate"); 8 jt.execute("insert into account(name,money)values('eee',1000)"); 9 } 10 11 }
c、增删改查操作
1 public class JdbcTemplateDemo3 { 2 3 public static void main(String[] args) throws DataAccessException { 4 //加载Spring配置文件,创建spring容器 5 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); 6 //根据id获取jdbc模板 7 JdbcTemplate jt = (JdbcTemplate)ac.getBean("jdbcTemplate"); 8 9 //保存 10 jt.update("insert into account(name,money)values(?,?)", "fff",300); 11 12 //更新 13 jt.update("update account set money = ? where id = ? ",5000,6); 14 15 //删除 16 jt.update("delete from account where id = ? ",6); 17 18 //查询一个 19 Account account = jt.query("select * from account where id = ?",new MyResultSetExctractor(),1); 20 List<Account> list = jt.query("select * from account where id = ?",new AccountRowMapper(),1); 21 Account account = null; 22 if(list.size() == 1){ 23 account = list.get(0); 24 } 25 System.out.println(account); 26 27 //查询所有 28 List<Account> list = jt.query("select * from account", new AccountRowMapper()); 29 System.out.println(list); 30 31 32 //查询返回一行一列的情况:比如count(*) 33 int totalRecords = jt.queryForObject("select count(*) from account", Integer.class); 34 System.out.println(totalRecords); 35 } 36 }
1 class AccountRowMapper implements RowMapper<Account>{ 2 3 /** 4 * 它是每次遍历都会调用一次此方法 5 * List<Account> list = new ArrayList<Account>(); 6 * while(rs.next){ 7 * Account account = mapRow(rs); 8 * list.add(acount); 9 * } 10 * return list; 11 */ 12 public Account mapRow(ResultSet rs, int rowNum) throws SQLException { 13 Account account = new Account(); 14 account.setId(rs.getInt("id")); 15 account.setName(rs.getString("name")); 16 account.setMoney(rs.getFloat("money")); 17 return account; 18 } 19 } 20 21 22 class MyResultSetExctractor implements ResultSetExtractor<Account>{ 23 24 public Account extractData(ResultSet rs) throws SQLException, DataAccessException { 25 Account account = null; 26 //1.判断是否有结果集 27 if(rs.next()){ 28 account = new Account(); 29 account.setId(rs.getInt("id")); 30 account.setName(rs.getString("name")); 31 account.setMoney(rs.getFloat("money")); 32 } 33 return account; 34 } 35 }
2.1.3、Spring提供的数据库访问的DAO工具类
JdbcDaoSupport:JdbcTemplate的Dao模式的抽取类
HibernateDaoSupport:HibernateTemplate的Dao模式的抽取类
a、原始版本: DAO中直接使用JdbcTemplate
b、改进版:DAO实现类继承JdbcDaoSupport,注入数据源即可
1 <!-- 配置一个JdbcTemplate的bean --> 2 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 3 <property name="dataSource" ref="driverManagerDataSource"></property> 4 </bean> 5 6 <!-- 配置数据源 --> 7 <bean id="driverManagerDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 8 <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 9 <property name="url" value="jdbc:mysql://localhost:3306/ee0413_spring_day36"></property> 10 <property name="username" value="root"></property> 11 <property name="password" value="1234"></property> 12 </bean>
1 public class AccountDaoImpl2 extends JdbcDaoSupport implements IAccountDao { 2 3 public void saveAccount(Account account) { 4 getJdbcTemplate().update("insert into account(name,money)values(?,?)",account.getName(),account.getMoney()); 5 } 6 7 }
c、关于原始版本和改进版的选择问题:
如果是基于XML的配置,则可以使用改进版,也就是Dao抽取类。
如果是基于注解的配置,我们需要在JdbcTemplate上添加注解,由Spring注入。但是JdbcTemplate对象的定义是在JdbcDaoSupport类中,是spring官方jar包里面的,我们修改不了。所以还要使用原始版本。
2.3、数据源
2.3.1、DBCP数据源 BasicDataSource
a、拷贝DBCP的必要jar包:
commons-dbcp.jar commons-pool.jar
b、配置基本的属性
2.3.2、C3P0数据源 ComboPooledDataSource
a、拷贝C3P0的必要jar包:
c3p0-0.9.1.2.jar
b、配置基本的属性
2.3.3、Spring内置数据源DriverManagerDataSource
1 <!-- 配置数据源 --> 2 <bean id="driverManagerDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 3 <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> 4 <property name="url" value="jdbc:mysql://localhost:3306/ee0413_spring_day36"></property> 5 <property name="username" value="root"></property> 6 <property name="password" value="1234"></property> 7 </bean>
2.3.4、对于原生JDBC配置的支持
把配置信息存到一个.properties文件中。