你的位置:首页 > Java教程

[Java教程]Spring(七)持久层


一、Spring对DAO的支持

 DAO:Data Access Object

Spring提供了DAO框架,让开发人员无须耦合特定的数据库技术,就能进行应用程序的开发。

Spring封闭了操作Oracle,MySql,DB2,SQL等数据库的用法。

它们都实现同一接口,方法也是一样的。

优势:

由于依赖于接口,可以通过依赖注入随时替换DAO接口的实现类,而应用程序完全不用了解接口与底层数据库操作细节。

应用程序----调用-----》DAO接口《---实现--DAO接口实现类----操作------》数据库

二、Spring注入数据源

2.1、 DataSource(数据源)

连接数据的方式称为“数据库”。比如JDBC,连接池或者JNDI

Spring通过依赖注入方式配置数据源

不同系统,数据源的管理更多是针对底层的行为,这些行为不应该影响业务。

更换数据只需修改Bean定义的内容,而不需要修改任何一行代码。

2.2、配置数据源

applicationContext.

<??><beans  ="http://www.springframework.org/schema/beans"  ="http://www.w3.org/2001/  ="http://www.springframework.org/schema/p"  ="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!--数据源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!--驱动 --><property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/><!--URL --><property name="url" value="jdbc:oracl:thin:@localhost:1521:orcl"/><!--连接的用户名 --><property name="username" value="accp"></property><!--连接的密码 --><property name="password" value="accp"></property></bean></beans>

 JDBC操作:

package com.pb.jdbc.dao.impl;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import javax.sql.DataSource;import com.pb.entity.Person;import com.pb.jdbc.dao.PersonDao;public class PersonDaoImpl implements PersonDao {  private DataSource dataSource;  @Override  public Person findById(Integer id) {    Connection con = null;    PreparedStatement ps = null;    ResultSet rs = null;    Person p=null;    String sql="select * from person where id=?";    Object [] params={id};    //获取连接    try {      con=dataSource.getConnection();      ps=con.prepareStatement(sql);      if(params!=null){      for (int i = 0; i < params.length; i++) {        ps.setObject(i+1, params[i]);      }      }      rs=ps.executeQuery();      if(rs!=null){        p=new Person();        while(rs.next()){          p.setId(rs.getInt("id"));          p.setName(rs.getString("name"));          p.setAge(rs.getInt("age"));        }      }      return p;    } catch (SQLException e) {      e.printStackTrace();    }finally{              try {          if(rs!=null)          rs.close();          if(ps!=null)            ps.close();          if(con!=null)            con.close();        } catch (SQLException e) {          e.printStackTrace();        }    }            return null;  }  public void setDataSource(DataSource dataSource) {    this.dataSource = dataSource;  }}

更新applicationContext.

<??><beans  ="http://www.springframework.org/schema/beans"  ="http://www.w3.org/2001/  ="http://www.springframework.org/schema/p"  ="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!--数据源 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!--驱动 --><property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/><!--URL --><property name="url" value="jdbc:oracl:thin:@localhost:1521:orcl"/><!--连接的用户名 --><property name="username" value="accp"></property><!--连接的密码 --><property name="password" value="accp"></property></bean><!-- PersonDao接口实现类 --><bean id="personDaoImpl" class="com.pb.jdbc.dao.impl.PersonDaoImpl"><!-- 属性关联 --><property name="dataSource" ref="dataSource"/></bean></beans>

 

三、JDBC Template

 为什么需要JDBCTemplate(JDBC模板)?

使用JDBC时,总是需要进行固定的步骤,比如Connection,Statement的获取、关闭,异常处理等。

JDBCTemplate作用:

Spring将JDBC常用的操作封装到JDBCTemplate中简化了使用JDBC的开发流程,开发人员不需要关心,获得连接和关闭连接

更改上面的代码

package com.pb.jdbc.dao.impl;import java.math.BigDecimal;import java.util.List;import java.util.Map;import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;import com.pb.entity.Person;import com.pb.jdbc.dao.PersonDao;public class JdbcTemplatePersonDaoImpl implements PersonDao {  private JdbcTemplate jdbcTemplate;  //根据ID查找  @Override  public Person findById(Integer id) {    Person p=null;    //返回的是集合,但集合的每个元素都是一个map    String sql="select * from person where id=?";    //占位符    Object [] params={id};    //调用SQL和占位    List results=jdbcTemplate.queryForList(sql,params);    for (Object object : results) {      Map personMap=(Map) object;      //获取每个map的值      Long p_id=((BigDecimal) personMap.get("ID")).longValue();      String p_name=(String) personMap.get("NAME");      Integer p_age=((BigDecimal) personMap.get("AGE")).intValue();            //声明      p=new Person();      p.setAge(p_age);      p.setId(p_id);      p.setName(p_name);    }        return p;  }  //通过设置数据获取JdbcTemplate的实例  public void setDataSource(DataSource dataSource) {    jdbcTemplate=new JdbcTemplate(dataSource);  }}

 

四、JDBC Template

要使用Jdbctemplate 对象来完成jdbc 操作。通常情况下,有三种种方式得到JdbcTemplate 对象。 

  •       第一种方式:我们可以在自己定义的DAO 实现类中注入一个DataSource 引用来完 成JdbcTemplate 的实例化。也就是它是从外部“注入” DataSource   到DAO 中,然后 自己实例化JdbcTemplate,然后将DataSource 设置到JdbcTemplate 对象中。 
  •       第二种方式: 在 Spring 的 IoC 容器中配置一个 JdbcTemplate 的 bean,将 DataSource 注入进来,然后再把JdbcTemplate 注入到自定义DAO 中。 
  •       第三种方式: Spring 提供了 org.springframework.jdbc.core.support.JdbcDaoSupport 类 , 这 个 类 中 定 义 了 JdbcTemplate 属性,也定义了DataSource 属性,当设置DataSource 属性的时候,会创 建jdbcTemplate 的实例,所以我们自己编写的DAO 只需要继承JdbcDaoSupport 类, 然后注入DataSource 即可

 第一种

public class UserServiceImpl implements UserService {    private JdbcTemplate jdbcTemplate;      public JdbcTemplate getJdbcTemplate() {     return jdbcTemplate;   }          //注入方法1     public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {     this.jdbcTemplate = jdbcTemplate;   }          //其它方法这里省略…… } 

application.

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">     <property name = "dataSource" ref="dataSource"> </bean> <bean id="userService" class="com.hxzy.account.jdbcTemplate.UserServiceImpl">    <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> 

第二种 通过数据库实例化JdbcTemplate

public class UserServiceImpl implements UserService {      private JdbcTemplate jdbcTemplate;          //注入方法2     public void setDataSource(DataSource dataSource) {           this.jdbcTemplate = new JdbcTemplate(dataSource);     }        //其它方法省略…… } 

applicationContext.

前提是已经配置了dataSource  2.2配置数据源

spring配置文件为:


<bean id="userService" class="com.hxzy.account.jdbcTemplate.UserServiceImpl">     <property name="dataSource" ref="dataSource"/> </bean> 

第三种:

继承JdbcDaoSupport,其内部有个JdbcTemplate ,需要注入DataSource 属性来实例化。

public class UserDaoImpl extends JdbcDaoSupport implements UserDao {    @Override   public void save(User user) {     String sql = null;     this.getJdbcTemplate().update(sql);   }     //其它方法省略…… } 

<bean id="userDao" class="com.hxzy.account.jdbcTemplate.UserDaoImpl">       <property name="dataSource" ref="dataSource"/> </bean> 

 


五、JDBC Template操作数据库

 执行DDL与更新

  • 使用JdbcTemplate的execute()方法可以执行DDL语句
  • 执行update或者inert,可以使用update()方法;

 

package com.pb.demo;import java.util.List;import java.util.Map;import javax.sql.DataSource;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathimport org.springframework.jdbc.core.JdbcTemplate;/** * 1.JdbcTemplate queryForXxx方法执行SQL语句 * 2. query和update都可以使用占位符 * 3. 返回的List中的元素为map * 4.使用update执行更新操作 * 5.使用execute方法执行DDL操作 */public class JdbcTemplateDemo {  public static void main(String[] args) {    ApplicationContext context=new ClassPath);    //获取数据源    DataSource dataSource=context.getBean("dataSource",DataSource.class);    //通过数据源实例JdbcTemplate    JdbcTemplate jt=new JdbcTemplate(dataSource);        //执行占位符的查询语句    String sql_v="select * from person where name=? and age=?";    Object [] params={"李四",24};    //传入参数    List result=jt.queryForList(sql_v,params);    for (Object object : result) {      //直接输出对象      System.out.println(object);      //或者输出值      Map map=(Map)object;      System.out.println("ID: "+map.get("ID")+"姓名:"+map.get("NAME")+map.get("AGE"));    }    //更新    String sql_update="update person set name=? where age=?";    //年龄为23的都更新为张小三    Object [] pupdate={"张小三",23};    //数据库受影响的行数    int count=jt.update(sql_update, pupdate);    System.out.println("更新了"+count+"行");      //查询总记录数    String sql_count="select count(*) from person";    int totalcount=jt.queryForInt(sql_count);    System.out.println("Person表的总记录数: "+totalcount);    //执行DDL语句    //创建一张表    String ddl="create table test(id number(4) primary key,name varchar2(50))";    jt.execute(ddl);    System.out.println("创建表 成功");    //删除表    String del_table="drop table test";    jt.execute(del_table);    System.out.println("删除表成功");          }}

配置数据如:2.2

 

package com.pb.demo;import java.sql.PreparedStatement;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import javax.sql.DataSource;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathimport org.springframework.jdbc.core.BatchPreparedStatementSetter;import org.springframework.jdbc.core.JdbcTemplate;/** * 使用批量处理数据 */public class JdbcTemplateDemo2 {  public static void main(String[] args) {    ApplicationContext context=new ClassPath);    //获取数据源    DataSource dataSource=context.getBean("dataSource",DataSource.class);    //通过数据源实例JdbcTemplate    JdbcTemplate jt=new JdbcTemplate(dataSource);      //批量插入数据    final int count=200;    final List id=new ArrayList();    final List name=new ArrayList();    final List password=new ArrayList();    //为集合调定值    for (int i = 0; i < count; i++) {      id.add(i);      name.add("name_"+i);      password.add("password_"+i);          }        //指处理数据    String sql="insert into users values(?,?,?)";    BatchPreparedStatementSetter bps=new BatchPreparedStatementSetter() {            @Override      public void setValues(PreparedStatement ps, int index) throws SQLException {        ps.setObject(1, id.get(index));        ps.setObject(2, name.get(index));        ps.setObject(3, password.get(index));              }            @Override      public int getBatchSize() {          return count;      }    };    //执行插入    jt.batchUpdate(sql, bps);    System.out.println("插入完成!");      }}

六、JDBC Template以对象方 式操作数据库

执行函数的类继承:

sqlfunction

package com.pb.object;import javax.sql.DataSource;import org.springframework.jdbc.object.SqlFunction;/** * 执行函数 * */public class PersonFunction extends SqlFunction{  public PersonFunction(DataSource ds){    //初始化    super(ds,"select count(*) from person");    //编译    compile();  }}

执行增加或者更新的类继承sqlupdate

package com.pb.object;import java.sql.Types;import javax.sql.DataSource;import org.springframework.jdbc.object.SqlUpdate;/** * 执行增加或者更新 * */public class PersonUpdate extends SqlUpdate {  public PersonUpdate(DataSource ds){    super(ds,"insert into person values(?,?,?)");    //设置参数为Oracle中的数据    int [] types={Types.BIGINT,Types.VARCHAR,Types.INTEGER};    //设置参数    setTypes(types);    compile();      }}

执行查询的类继承MappingSqlQuery

package com.pb.object;import java.sql.ResultSet;import java.sql.SQLException;import javax.sql.DataSource;import org.springframework.jdbc.object.MappingSqlQuery;import com.pb.entity.Person;/** * 对象查询 * @author Administrator * */public class PersonQuery extends MappingSqlQuery {  public PersonQuery(DataSource ds){    super(ds,"select * from person");    compile();  }  @Override  protected Object mapRow(ResultSet rs, int rownum) throws SQLException {    Person p=new Person();    p.setAge(rs.getInt("age"));    p.setId(rs.getLong("id"));    p.setName(rs.getString("name"));        return p;  }}

实现类和接口

package com.pb.dao;import java.util.List;import com.pb.entity.Person;public interface PersonDao {  //查询全部  public List<Person> find();  //增加  public void update(Person p);  //查询总记录数  public int getCount();          }

实现类

package com.pb.dao.impl;import java.util.List;import javax.sql.DataSource;import com.pb.dao.PersonDao;import com.pb.entity.Person;import com.pb.object.PersonFunction;import com.pb.object.PersonQuery;import com.pb.object.PersonUpdate;public class ObjectPersonDaoImpl implements PersonDao {  //3个实现类  private PersonFunction pf=null; //执行函数  private PersonQuery pq=null; //执行查询  private PersonUpdate pu=null; //执行更新    /*   *通过注入数据源实例化对象   *   */  public void setDataSource(DataSource ds){    pf=new PersonFunction(ds);    pq=new PersonQuery(ds);    pu=new PersonUpdate(ds);  }      @Override  public List<Person> find() {        return pq.execute();  }  @Override  public void update(Person p) {    //传入参数    pu.update(p.getId(),p.getName(),p.getAge());  }  @Override  public int getCount() {    //函数使用run运行调用    return pf.run();  }}

applicationContext.

<??><beans  ="http://www.springframework.org/schema/beans"  ="http://www.w3.org/2001/  ="http://www.springframework.org/schema/p"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/><property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/><property name="username" value="accp"/><property name="password" value="accp"/></bean><bean id="objectPersonDao" class="com.pb.dao.impl.ObjectPersonDaoImpl"><property name="dataSource" ref="dataSource"></property></bean></beans>

 

 

测试类

package com.pb.demo;import java.util.List;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathimport com.pb.dao.PersonDao;import com.pb.entity.Person;public class TestObjectJdbc {  public static void main(String[] args) {    ApplicationContext context=new ClassPath);        PersonDao opd=context.getBean("objectPersonDao",PersonDao.class);    Person p=new Person();    p.setAge(99);    p.setId(7);    p.setName("灭绝师太");        opd.update(p);        List<Person> persons=opd.find();        //调用查询总记录数的方法    System.out.println("总记录数:"+opd.getCount());    for (Person per : persons) {      System.out.println("ID:"+per.getId()+"姓名:"+per.getName()+" 年龄:"+per.getAge());    }  }}