Spring 之 ORM (JdbcTemplate)

 JdbcTemplate 简介

       

         spring 提供了不同持久层的技术的支持! ORM持久化技术  主要包含: JDBC,Hibernate,IBatis(MyBatis),JPA

       对应的模板类如下:
          ①JDBC               org.springframework.jdbc.core.JdbcTemplate
          ②Hibernate           org.springframework.orm.hibernate4.HibernateTemplate
          ③ IBatis(MyBatis)    org.springframework.orm.ibatis.SqlMapClientTemplate
          ④ JPA                    org.springframwork.orm.jpa.JpaTemplate

      其中 JdbcTempate 简称JDBC 编程!

  spring jdbc 框架   

      Srping  JDBC 框架(Spring-jdbc-x.x.x.x.RELEASE.jar) 由4个部分组成

              ① core 包: 提供了JDBC 模板类,JdbcTemplate 是core包的核心类!
              ② dataSource 包: 提供简化访问JDBC 数据源的工具类!
                    -- 并提供一些DataSource 简单实现类,从而使用DataSource 获取连接并得到Spring 的事务支持!
              ③ object 包,提供关系型数据的对象表现形式,如MappingSqlQuery,SqlUpdate,SqlCall,SqlFunction 等
              ④ support 包, 提供将JDBC 异常转换为DAO 非检查异常的转换类和一些工具类!

   

Jdbc 编程快速入门  

          第一步:maven 依赖 



    org.springframework
    spring-context
    4.3.9.RELEASE



    org.aspectj
    aspectjweaver
    1.8.9


    cglib
    cglib
    3.2.4

 

    org.springframework
    spring-jdbc
    4.3.9.RELEASE


    org.springframework
    spring-tx
    4.3.9.RELEASE




    mysql
    mysql-connector-java
    5.1.29
      第二步: 配置连接/并执行SQL        

public  void testNoConfigTemplate(){
    //获取数据源
    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setDriverClassName("org.gjt.mm.mysql.Driver");
    dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test");
    dataSource.setUsername("root");
    dataSource.setPassword("root99999");
    JdbcTemplate template = new JdbcTemplate(dataSource);
    template.execute("create table t_user(id INT ,NAME VARCHAR (2))");
}

       或 xml 配置


id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
    name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
    name="username" value="root"/>
    name="password" value="root99999"/>



id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    name="dataSource" ref="dataSource"/>
@Autowired
private  JdbcTemplate template;

@Test
public  void testXmlTemplate(){
    template.execute("INSERT INTO  t_user VALUES (2,'王wu')");
}       


Spring 连接池

      Spring 自带 DriverManagerDataSource 连接池


id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
    name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
    name="username" value="root"/>
    name="password" value="root99999"/>

            

       DBCP数据源

          DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。但是 dbcp没有自动的去回收空闲连接的功能! 

   commons-dbcp现在分成了3个大版本,不同的版本要求的JDK不同:
  DBCP now comes in three different versions to support different versions of JDBC. Here is how it works:
  DBCP 2 compiles and runs under Java 7 only (JDBC 4.1)
  DBCP 1.4 compiles and runs under Java 6 only (JDBC 4)
  DBCP 1.3 compiles and runs under Java 1.4-5 only (JDBC 3)

            对应的maven依赖如下: 


    org.apache.commons
    commons-dbcp2
    2.2.0
            xml 文件配置-- 具体配置 参考 << DBCP2配置详细说明 > >

id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
      destroy-method="close">
    name="driverClassName" value="org.gjt.mm.mysql.Driver" />
    name="url" value="jdbc:mysql://127.0.0.1:3306/test" />
    name="username" value="root" />
    name="password" value="password" />
    name="initialSize" value="10" />
    name="maxTotal" value="100" /> 
    name="maxIdle" value="100" />  
    name="maxWaitMillis" value="-1" /> 
  C3P0 数据源

 C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。并且 c3p0有自动回收空闲连接功能!

       对应的maven依赖如下:


    com.mchange
    c3p0
    0.9.5.2

xml 具体配置 --请参考< c3p0详细配置>>

id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

    name="driverClass" value="${jdbc.driverClass}" />

    name="jdbcUrl" value="${jdbc.jdbcUrl}" />

    name="user" value="${jdbc.user}" />

    name="password" value="${jdbc.password}" />

    name="minPoolSize" value="${jdbc.miniPoolSize}" />

    name="maxPoolSize" value="${jdbc.maxPoolSize}"/>

    name="initialPoolSize" value="${jdbc.initialPoolSize}"/>

    name="maxIdleTime" value="${jdbc.maxIdleTime}"/>

    name="acquireIncrement" value="${jdbc.acquireIncrement}"/>

    name="acquireRetryAttempts" value="${jdbc.acquireRetryAttempts}"/>

    name="acquireRetryDelay" value="${jdbc.acquireRetryDelay}"/>

    name="testConnectionOnCheckin" value="${jdbc.testConnectionOnCheckin}"/>

    name="automaticTestTable" value="${jdbc.automaticTestTable}"/>

    name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/>

    name="checkoutTimeout" value="${jdbc.checkoutTimeout}"/>


druid

Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。

Druid是一个JDBC组件,它包括三个部分:

  • 基于Filter-Chain模式的插件体系。
  • DruidDataSource 高效可管理的数据库连接池。
  • SQLParser
支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。Druid针对Oracle和MySql做了特别优化,比如Oracle的PS Cache内存占用优化,MySql的ping检测优化。Druid提供了MySql、Oracle、Postgresql、SQL-92的SQL的完整支持,这是一个手写的高性能SQL Parser,支持Visitor模式,使得分析SQL的抽象语法树很方便。简单SQL语句用时10微秒以内,复杂SQL用时30微秒。通过Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析语义实现的。

 对应的maven依赖


    com.alibaba
    druid
    1.1.6
xml 具体配置-- 具体配置请参考


<context:property-placeholder location="classpath:db.properties" />

id="dataSource"
      class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    
    name = "url" value = "${jdbc.url}" />
    name = "username" value = "${jdbc.username}" />
    name = "password" value = "${jdbc.password}" />
    name = "driverClassName" value = "${jdbc.driverClassName}" />
    name = "filters" value = "${jdbc.filters}" />
    
    name = "maxActive" value = "${jdbc.maxActive}" />
    
    name = "initialSize" value = "${jdbc.initialSize}" />
    
    name = "maxWait" value = "${jdbc.maxWait}" />
    
    name = "minIdle" value = "${jdbc.minIdle}" />
    
    name = "timeBetweenEvictionRunsMillis" value ="${jdbc.timeBetweenEvictionRunsMillis}" />
    
    name = "minEvictableIdleTimeMillis" value ="${jdbc.minEvictableIdleTimeMillis}" />
    
    name = "validationQuery" value = "${jdbc.validationQuery}" />
    
    name = "testWhileIdle" value = "${jdbc.testWhileIdle}" />
    
    name = "testOnBorrow" value = "${jdbc.testOnBorrow}" />
    
    name = "testOnReturn" value = "${jdbc.testOnReturn}" />
    
    name = "removeAbandoned" value = "${jdbc.removeAbandoned}" />
    
    name = "removeAbandonedTimeout" value ="${jdbc.removeAbandonedTimeout}" />
    
    name = "logAbandoned" value = "${jdbc.logAbandoned}" />


基于JdbcTemplate 的CRUD

     一. DAO 注入 Template

               为了方便DAO 中注入JdbcTemplate ,Spring 为每一个持久化技术都提供了支持类

Spring 之 ORM (JdbcTemplate)_第1张图片

     所以,DAO 注入Template 只需继承对应的Support 类,便会自动注入模板的方法

public class CustomerDao extends JdbcDaoSupport {

    public void createTable(){
        String sql="create table customer(id INT ,NAME VARCHAR (20),age INT )";
        super.getJdbcTemplate().execute(sql);
    }
   二.基于JdbcTemplate 实现增,删,改,查


方法名称 说明
void execute(String sql) 可以用于任何sql语句
int update(String sql,Object..args) 执行DML语句,如UPDATE、INSERT、DELETE,args是其对应的参数
List query(String sql,RowMapper rowMapper) 执行sql查询语句,并根据RowMapper具体的实现类返回结果类型
int queryForInt(String sql) queryForXXX(),XXX代表结果类型,执行sql查询语句,返回结果是整数
T queryForObject(String sql,Object[] args,RowMapper rowMapper) 根据sql语句和参数返回结果对象
List> queryForList(String sql,Object..args) 根据sql语句和参数返回结果列表,每个Map的key是列名,value是该列对应的数据

 采用update 实现 增,删,改

/**
 * 添加用户
 * @param customer
 */
public void sava(Customer customer){
    String sql=" insert into customer values(?,?,?)";
    super.getJdbcTemplate().update(sql,customer.getId(),customer.getName(),customer.getAge());
}

/**
 * 更新用户信息
 * @param customer
 */
public void update(Customer customer){
    String sql="update customer set name=?,age=? where id=?";
    super.getJdbcTemplate().update(sql,customer.getName(),customer.getAge(),customer.getId());
}

/**
 * 删除用户
 * @param customer
 */
public void delete(Customer customer){
    String sql="DELETE  FROM  customer where id=?";
    super.getJdbcTemplate().update(sql,customer.getId());

}

  三.查询

       基于JdbcTemplate 实现简单返回结果查询       

/**
 * 查询返回简单的对象的名称
 * @param id
 * @return
 */
public String findCustomerName(Integer id){
    String sql="select name from customer where id=?";
    return  super.getJdbcTemplate().queryForObject(sql,String.class,id);
}

    基于 JdbcTemplate 实现复杂对象 需要使用RowMapper 接口

             RowMapper 即一个接口,实现将表中的一行数据转换为一个对象!(如果列名和属性名一致,sping 3 使用ParameterizedBeanPropertyRowMapper 进行自动封装,如果是 Spring4 需要使用BeanPropertyRowMapper 进行自动封装! 如果列名和属性名 不一致需要进行自定义封装!
 )

**
 * 查询具体某个用户信息
 * @param id
 * @return
 */
public  Customer findCustomerById(Integer id){
    String sql="select * from customer where id =?";
    return  super.getJdbcTemplate().queryForObject(sql, BeanPropertyRowMapper.newInstance(Customer.class),id);
}

/**
 * 查询所有的用户信息
 * @return
 */
public List findCustomerAll(){
    String sql="select * from customer";
    return  super.getJdbcTemplate().query(sql,BeanPropertyRowMapper.newInstance(Customer.class));
}
        

JdbcTemplate支持对存储过程的调用

Spring JdbcTemplate支持对存储过程的调用(JDK最低1.5版本),JdbcTemplate支持的存储过程回调类如下:

——CallableStatementCreator:

通过回调获取JdbcTemplate提供的Connection,由用户使用该Connection创建相关的CallableStatement

——CallableStatementCallback:

通过回调获取JdbcTemplate提供的CallableStatement,用户可以再CallableStatement执行任何操作


1)执行无返回值的存储过程:

[java]  view plain  copy
  1. package com.wzj.test;  
  2.   
  3.   
  4. import org.springframework.jdbc.core.JdbcTemplate;  
  5.   
  6.   
  7. public class Demo{  
  8.     private JdbcTemplate jdbcTemplate;  
  9.     //省略get、set  
  10.       
  11.     public void test(){  
  12.         jdbcTemplate.execute("{call procedureName(param,param...)}");  
  13.     }  
  14. }  

(2)执行返回非结果集的存储过程:

创建存储过程:
[sql]  view plain  copy
  1. create or replace procedure get_user_name(id in varchar2,username out varchar2) is  
  2. begin  
  3.     select username from User where userid=id;  
  4. end  
调用:
[java]  view plain  copy
  1. public void test(){  
  2.     jdbcTemplate.execute(new CallableStatementCreator() {  
  3.         @Override  
  4.         public CallableStatement createCallableStatement(Connection con)  
  5.                 throws SQLException {  
  6.             String userid="22";  
  7.             //创建对象  
  8.             CallableStatement cs=con.prepareCall("call get_user_name(?,?)");  
  9.             //设置参数  
  10.             cs.setString(1, userid);  
  11.             //设置输出参数  
  12.             cs.registerOutParameter(2, OracleTypes.VARCHAR);  
  13.             return cs;  
  14.         }  
  15.     }, new CallableStatementCallback() {  
  16.         @Override  
  17.         public Object doInCallableStatement(CallableStatement cs)  
  18.                 throws SQLException, DataAccessException {  
  19.             //执行存储过程  
  20.             cs.execute();  
  21.             //获取输出参数  
  22.             return cs.getString(2);  
  23.         }  
  24.     });  
  25. }  

(3)执行返回结果集的存储过程:

①建立程序包:
[sql]  view plain  copy
  1. create or replace package userpackage as   
  2.   type user_cursor is ref cursor;   
  3. end userpackage;   
②创建存储过程:
[sql]  view plain  copy
  1. create or replace procedure get_user(user_cursor out userpackage.user_cursor) is   
  2. begin   
  3.      open user_cursor for select * from User;   
  4. end;   
③调用:
[java]  view plain  copy
  1. public void test() {   
  2.     List userList = (List) jdbcTemplate.execute(   
  3.             new CallableStatementCreator() {   
  4.                 public CallableStatement createCallableStatement(Connection con) throws SQLException {   
  5.                     CallableStatement cs = con.prepareCall("{call get_user(?)}");   
  6.                     cs.registerOutParameter(1, OracleTypes.CURSOR);// 注册输出参数的类型   
  7.                     return cs;   
  8.                 }   
  9.             }, new CallableStatementCallback() {   
  10.                 public Object doInCallableStatement(CallableStatement cs) throws SQLException,DataAccessException {   
  11.                     List userMap = new ArrayList();   
  12.                     cs.execute();   
  13.                     ResultSet rs = (ResultSet) cs.getObject(1);// 获取游标一行的值   
  14.                     while (rs.next()) {// 转换每行的返回值到Map中   
  15.                         Map rowMap = new HashMap();   
  16.                         rowMap.put("userid", rs.getString("userid"));   
  17.                         rowMap.put("username", rs.getString("username"));   
  18.                         userMap.add(rowMap);   
  19.                     }   
  20.                     rs.close();   
  21.                     return userMap;   
  22.                 }   
  23.             });   
  24.     for (int i = 0; i < userList.size(); i++) {   
  25.         Map rowMap = (Map) userList.get(i);   
  26.         String id = rowMap.get("userid").toString();   
  27.         String name = rowMap.get("username").toString();   
  28.         System.out.println("usreid=" + id + ";username=" + name);   
  29.     }   
  30. }   

你可能感兴趣的:(开发框架)