JdbcTemplate主要提供以下五类方法:-程序员宅基地

技术标签: JAVA  方法  数据库  JdbcTemplate  

原文格式更清晰,转载自:https://blog.csdn.net/qmdweb/article/details/81224330

 

 

 

   

JdbcTemplate主要提供以下五类方法:

execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句;
call方法:用于执行存储过程、函数相关语句。
 

JdbcTemplate类支持的回调类:

预编译语句及存储过程创建回调:用于根据JdbcTemplate提供的连接创建相应的语句;
         PreparedStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的PreparedStatement;

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

预编译语句设值回调:用于给预编译语句相应参数设值;
         PreparedStatementSetter:通过回调获取JdbcTemplate提供的PreparedStatement,由用户来对相应的预编译语句相应参数设值;

         BatchPreparedStatementSetter:;类似于PreparedStatementSetter,但用于批处理,需要指定批处理大小;

自定义功能回调:提供给用户一个扩展点,用户可以在指定类型的扩展点执行任何数量需要的操作;
         ConnectionCallback:通过回调获取JdbcTemplate提供的Connection,用户可在该Connection执行任何数量的操作;

         StatementCallback:通过回调获取JdbcTemplate提供的Statement,用户可以在该Statement执行任何数量的操作;

         PreparedStatementCallback:通过回调获取JdbcTemplate提供的PreparedStatement,用户可以在该PreparedStatement执行任何数量的操作;

         CallableStatementCallback:通过回调获取JdbcTemplate提供的CallableStatement,用户可以在该CallableStatement执行任何数量的操作;

结果集处理回调:通过回调处理ResultSet或将ResultSet转换为需要的形式;
         RowMapper:用于将结果集每行数据转换为需要的类型,用户需实现方法mapRow(ResultSet rs, int rowNum)来完成将每行数据转换为相应的类型。

         RowCallbackHandler:用于处理ResultSet的每一行结果,用户需实现方法processRow(ResultSet rs)来完成处理,在该回调方法中无需执行rs.next(),该操作由JdbcTemplate来执行,用户只需按行获取数据然后处理即可。

         ResultSetExtractor:用于结果集数据提取,用户需实现方法extractData(ResultSet rs)来处理结果集,用户必须处理整个结果集;

 

接下来让我们看下具体示例吧,
在示例中不可能介绍到JdbcTemplate全部方法及回调类的使用方法,我们只介绍代表性的,其余的使用都是类似的:

 

1)预编译语句及存储过程创建回调、自定义功能回调使用:

 

java代码:

Java代码  

@Test  
public void testPpreparedStatement1() {  
  int count = jdbcTemplate.execute(new PreparedStatementCreator() {  
     @Override  
     public PreparedStatement createPreparedStatement(Connection conn)  
         throws SQLException {  
         return conn.prepareStatement("select count(*) from test");  
     }}, new PreparedStatementCallback<Integer>() {  
     @Override  
     public Integer doInPreparedStatement(PreparedStatement pstmt)  
         throws SQLException, DataAccessException {  
         pstmt.execute();  
         ResultSet rs = pstmt.getResultSet();  
         rs.next();  
         return rs.getInt(1);  
      }});      
   Assert.assertEquals(0, count);  
}  
   
 

首先使用PreparedStatementCreator创建一个预编译语句,其次由JdbcTemplate通过PreparedStatementCallback回调传回,由用户决定如何执行该PreparedStatement。此处我们使用的是execute方法。

 

2)预编译语句设值回调使用:

 

java代码:

Java代码  

      
@Test  
public void testPreparedStatement2() {  
  String insertSql = "insert into test(name) values (?)";  
  int count = jdbcTemplate.update(insertSql, new PreparedStatementSetter() {  
      @Override  
      public void setValues(PreparedStatement pstmt) throws SQLException {  
          pstmt.setObject(1, "name4");  
  }});  
  Assert.assertEquals(1, count);      
  String deleteSql = "delete from test where name=?";  
  count = jdbcTemplate.update(deleteSql, new Object[] {"name4"});  
  Assert.assertEquals(1, count);  
}  
 

      通过JdbcTemplate的int update(String sql, PreparedStatementSetter pss)执行预编译sql,其中sql参数为“insert into test(name) values (?) ”,该sql有一个占位符需要在执行前设值,PreparedStatementSetter实现就是为了设值,使用setValues(PreparedStatement pstmt)回调方法设值相应的占位符位置的值。JdbcTemplate也提供一种更简单的方式“update(String sql, Object... args)”来实现设值,所以只要当使用该种方式不满足需求时才应使用PreparedStatementSetter。

 

3)结果集处理回调:

 

java代码:

Java代码  

@Test  
public void testResultSet1() {  
  jdbcTemplate.update("insert into test(name) values('name5')");  
  String listSql = "select * from test";  
  List result = jdbcTemplate.query(listSql, new RowMapper<Map>() {  
      @Override  
      public Map mapRow(ResultSet rs, int rowNum) throws SQLException {  
          Map row = new HashMap();  
          row.put(rs.getInt("id"), rs.getString("name"));  
          return row;  
  }});  
  Assert.assertEquals(1, result.size());  
  jdbcTemplate.update("delete from test where name='name5'");       
}  
 

RowMapper接口提供mapRow(ResultSet rs, int rowNum)方法将结果集的每一行转换为一个Map,当然可以转换为其他类,如表的对象画形式。

 

java代码:

Java代码  

@Test  
public void testResultSet2() {  
  jdbcTemplate.update("insert into test(name) values('name5')");  
  String listSql = "select * from test";  
  final List result = new ArrayList();  
  jdbcTemplate.query(listSql, new RowCallbackHandler() {  
      @Override  
      public void processRow(ResultSet rs) throws SQLException {  
          Map row = new HashMap();  
          row.put(rs.getInt("id"), rs.getString("name"));  
          result.add(row);  
  }});  
  Assert.assertEquals(1, result.size());  
  jdbcTemplate.update("delete from test where name='name5'");  
}  
 

RowCallbackHandler接口也提供方法processRow(ResultSet rs),能将结果集的行转换为需要的形式。

 

java代码:

Java代码  

@Test  
public void testResultSet3() {  
  jdbcTemplate.update("insert into test(name) values('name5')");  
  String listSql = "select * from test";  
  List result = jdbcTemplate.query(listSql, new ResultSetExtractor<List>() {  
      @Override  
      public List extractData(ResultSet rs)  
     throws SQLException, DataAccessException {  
          List result = new ArrayList();  
          while(rs.next()) {  
              Map row = new HashMap();  
              row.put(rs.getInt("id"), rs.getString("name"));  
              result.add(row);  
           }  
           return result;  
  }});  
  Assert.assertEquals(0, result.size());  
  jdbcTemplate.update("delete from test where name='name5'");  
}  
 

ResultSetExtractor使用回调方法extractData(ResultSet rs)提供给用户整个结果集,让用户决定如何处理该结果集。

 

当然JdbcTemplate提供更简单的queryForXXX方法,来简化开发(重点!!):

java代码:

//1.查询一行数据并返回int型结果  
jdbcTemplate.queryForInt("select count(*) from test");  
//2. 查询一行数据并将该行数据转换为Map返回  
jdbcTemplate.queryForMap("select * from test where name='name5'");  
//3.查询一行任何类型的数据,最后一个参数指定返回结果类型  
jdbcTemplate.queryForObject("select count(*) from test", Integer.class);  
//4.查询一批数据,默认将每行数据转换为Map       
jdbcTemplate.queryForList("select * from test");  
//5.只查询一列数据列表,列类型是String类型,列名字是name  
jdbcTemplate.queryForList("select name from test where name=?", new Object[]{"name5"}, String.class);  
//6.查询一批数据,返回为SqlRowSet,类似于ResultSet,但不再绑定到连接上  
SqlRowSet rs = jdbcTemplate.queryForRowSet("select * from test");  

 

3) 存储过程及函数回调:

首先修改JdbcTemplateTest的setUp方法,修改后如下所示:

 

 

java代码:

Java代码  

      
@Before  
public void setUp() {  
    String createTableSql = "create memory table test" +  
    "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " +  
    "name varchar(100))";  
    jdbcTemplate.update(createTableSql);  
         
    String createHsqldbFunctionSql =  
      "CREATE FUNCTION FUNCTION_TEST(str CHAR(100)) " +  
      "returns INT begin atomic return length(str);end";  
    jdbcTemplate.update(createHsqldbFunctionSql);  
    String createHsqldbProcedureSql =  
      "CREATE PROCEDURE PROCEDURE_TEST" +  
      "(INOUT inOutName VARCHAR(100), OUT outId INT) " +  
      "MODIFIES SQL DATA " +  
      "BEGIN ATOMIC " +  
      "  insert into test(name) values (inOutName); " +  
      "  SET outId = IDENTITY(); " +  
      "  SET inOutName = 'Hello,' + inOutName; " +  
    "END";  
    jdbcTemplate.execute(createHsqldbProcedureSql);  
}  
 

       其中CREATE FUNCTION FUNCTION_TEST用于创建自定义函数,CREATE PROCEDURE PROCEDURE_TEST用于创建存储过程,注意这些创建语句是数据库相关的,本示例中的语句只适用于HSQLDB数据库。

 

       其次修改JdbcTemplateTest的tearDown方法,修改后如下所示:

 

java代码:

Java代码  

@After  
public void tearDown() {  
    jdbcTemplate.execute("DROP FUNCTION FUNCTION_TEST");  
    jdbcTemplate.execute("DROP PROCEDURE PROCEDURE_TEST");  
    String dropTableSql = "drop table test";  
    jdbcTemplate.execute(dropTableSql);  
}  
 

       其中drop语句用于删除创建的存储过程、自定义函数及数据库表。

 

       接下来看一下hsqldb如何调用自定义函数:

 

java代码:

Java代码  

@Test  
public void testCallableStatementCreator1() {  
    final String callFunctionSql = "{call FUNCTION_TEST(?)}";  
    List<SqlParameter> params = new ArrayList<SqlParameter>();  
    params.add(new SqlParameter(Types.VARCHAR));  
    params.add(new SqlReturnResultSet("result",  
       new ResultSetExtractor<Integer>() {  
           @Override  
           public Integer extractData(ResultSet rs) throws SQLException,  
               DataAccessException {  
               while(rs.next()) {  
                   return rs.getInt(1);  
               }  
              return 0;  
       }));  
    Map<String, Object> outValues = jdbcTemplate.call(  
       new CallableStatementCreator() {  
            @Override  
            public CallableStatement createCallableStatement(Connection conn) throws SQLException {  
              CallableStatement cstmt = conn.prepareCall(callFunctionSql);  
              cstmt.setString(1, "test");  
              return cstmt;  
    }}, params);  
    Assert.assertEquals(4, outValues.get("result"));  
}  
   
 

{call FUNCTION_TEST(?)}:定义自定义函数的sql语句,注意hsqldb {?= call …}和{call …}含义是一样的,而比如mysql中两种含义是不一样的;
params:用于描述自定义函数占位符参数或命名参数类型;SqlParameter用于描述IN类型参数、SqlOutParameter用于描述OUT类型参数、SqlInOutParameter用于描述INOUT类型参数、SqlReturnResultSet用于描述调用存储过程或自定义函数返回的ResultSet类型数据,其中SqlReturnResultSet需要提供结果集处理回调用于将结果集转换为相应的形式,hsqldb自定义函数返回值是ResultSet类型。
CallableStatementCreator:提供Connection对象用于创建CallableStatement对象
outValues:调用call方法将返回类型为Map<String, Object>对象;
outValues.get("result"):获取结果,即通过SqlReturnResultSet对象转换过的数据;其中SqlOutParameter、SqlInOutParameter、SqlReturnResultSet指定的name用于从call执行后返回的Map中获取相应的结果,即name是Map的键。
注:因为hsqldb {?= call …}和{call …}含义是一样的,因此调用自定义函数将返回一个包含结果的ResultSet。

 

最后让我们示例下mysql如何调用自定义函数:

 

java代码:

Java代码  

@Test  
public void testCallableStatementCreator2() {  
    JdbcTemplate mysqlJdbcTemplate = new JdbcTemplate(getMysqlDataSource);  
    //2.创建自定义函数  
String createFunctionSql =  
    "CREATE FUNCTION FUNCTION_TEST(str VARCHAR(100)) " +  
     "returns INT return LENGTH(str)";  
String dropFunctionSql = "DROP FUNCTION IF EXISTS FUNCTION_TEST";  
mysqlJdbcTemplate.update(dropFunctionSql);         
mysqlJdbcTemplate.update(createFunctionSql);  
//3.准备sql,mysql支持{?= call …}  
final String callFunctionSql = "{?= call FUNCTION_TEST(?)}";  
//4.定义参数  
List<SqlParameter> params = new ArrayList<SqlParameter>();  
params.add(new SqlOutParameter("result", Types.INTEGER));  
params.add(new SqlParameter("str", Types.VARCHAR));  
Map<String, Object> outValues = mysqlJdbcTemplate.call(  
new CallableStatementCreator() {  
    @Override  
    public CallableStatement createCallableStatement(Connection conn) throws SQLException {  
      CallableStatement cstmt = conn.prepareCall(callFunctionSql);  
      cstmt.registerOutParameter(1, Types.INTEGER);  
      cstmt.setString(2, "test");  
        return cstmt;  
    }}, params);  
   Assert.assertEquals(4, outValues.get("result"));  
}  
public DataSource getMysqlDataSource() {  
    String url = "jdbc:mysql://localhost:3306/test";  
    DriverManagerDataSource dataSource =  
        new DriverManagerDataSource(url, "root", "");     dataSource.setDriverClassName("com.mysql.jdbc.Driver");  
    return dataSource;  
}  
   
getMysqlDataSource:首先启动mysql(本书使用5.4.3版本),其次登录mysql创建test数据库(“create database test;”),在进行测试前,请先下载并添加mysql-connector-java-5.1.10.jar到classpath;
{?= call FUNCTION_TEST(?)}:可以使用{?= call …}形式调用自定义函数;
params:无需使用SqlReturnResultSet提取结果集数据,而是使用SqlOutParameter来描述自定义函数返回值;
CallableStatementCreator:同上个例子含义一样;
cstmt.registerOutParameter(1, Types.INTEGER):将OUT类型参数注册为JDBC类型Types.INTEGER,此处即返回值类型为Types.INTEGER。
outValues.get("result"):获取结果,直接返回Integer类型,比hsqldb简单多了吧。
 

最后看一下如何如何调用存储过程:

 

java代码:

Java代码  

@Test  
public void testCallableStatementCreator3() {  
    final String callProcedureSql = "{call PROCEDURE_TEST(?, ?)}";  
    List<SqlParameter> params = new ArrayList<SqlParameter>();  
    params.add(new SqlInOutParameter("inOutName", Types.VARCHAR));  
    params.add(new SqlOutParameter("outId", Types.INTEGER));  
    Map<String, Object> outValues = jdbcTemplate.call(  
      new CallableStatementCreator() {  
        @Override  
        public CallableStatement createCallableStatement(Connection conn) throws SQLException {  
          CallableStatement cstmt = conn.prepareCall(callProcedureSql);  
          cstmt.registerOutParameter(1, Types.VARCHAR);  
          cstmt.registerOutParameter(2, Types.INTEGER);  
          cstmt.setString(1, "test");  
          return cstmt;  
    }}, params);  
    Assert.assertEquals("Hello,test", outValues.get("inOutName"));  
    Assert.assertEquals(0, outValues.get("outId"));  
}  
   
{call PROCEDURE_TEST(?, ?)}:定义存储过程sql;
params:定义存储过程参数;SqlInOutParameter描述INOUT类型参数、SqlOutParameter描述OUT类型参数;
CallableStatementCreator:用于创建CallableStatement,并设值及注册OUT参数类型;
outValues:通过SqlInOutParameter及SqlOutParameter参数定义的name来获取存储过程结果。
 

       JdbcTemplate类还提供了很多便利方法,在此就不一一介绍了,但这些方法是由规律可循的,第一种就是提供回调接口让用户决定做什么,第二种可以认为是便利方法(如queryForXXX),用于那些比较简单的操作。

 

更多关系Spring的信息

 Spring 论坛  http://www.itchm.com/forum-59-1.html

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~另一篇~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

原文格式更清晰,原文地址:http://www.cnblogs.com/caoyc/p/5630622.html   尊重原创,请访问原文地址

JdbcTemplate简介

  Spring对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中。

  JdbcTemplate位于中。其全限定命名为org.springframework.jdbc.core.JdbcTemplate。要使用JdbcTemlate还需一个这个包包含了一下事务和异常控制

  

JdbcTemplate主要提供以下五类方法:

execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
query方法及queryForXXX方法:用于执行查询相关语句;
call方法:用于执行存储过程、函数相关语句。
 

下面进行案件分析

 

在src下面新建一个属性配置文件

1 jdbc.user=root
2 jdbc.password=123456
3 jdbc.driverClass=com.mysql.jdbc.Driver
4 jdbc.jdbcUrl=jdbc\:mysql\:///test
  我们通常将数据库的配置信息单独放到一个文件中,这样也为了方便后期维护

 

配置Spring配置文件applicationContext.xml

 1 <context:property-placeholder location="classpath:db.properties"/>
 2 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 3     <property name="user" value="${jdbc.user}"></property>
 4     <property name="password" value="${jdbc.password}"></property>
 5     <property name="driverClass" value="${jdbc.driverClass}"></property>
 6     <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
 7 </bean>
 8 
 9 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
10     <property name="dataSource" ref="dataSource"></property>
11 </bean>


  第一行代码:用来读取db.properties文件中的数据。

  第二行代码:用来配置一个数据源,这里数据实现类来自C3P0中的一个属性类。其中属性的值就是来自于db.properties

  第九行代码:配置一个JdbcTemplate实例,并注入一个dataSource数据源

 

测试代码
 

1、update()方法
 

a、通过update插入数据

1 //启动IoC容器
2 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
3 //获取IoC容器中JdbcTemplate实例
4 JdbcTemplate jdbcTemplate=(JdbcTemplate) ctx.getBean("jdbcTemplate");
5 String sql="insert into user (name,deptid) values (?,?)";
6 int count= jdbcTemplate.update(sql, new Object[]{"caoyc",3});
7 System.out.println(count);


  这里update方法,第二参可以为可变参数。在数据库中可以看到,数据以被正确插入

 

b、通过update修改数据

1 String sql="update user set name=?,deptid=? where id=?";
2 jdbcTemplate.update(sql,new Object[]{"zhh",5,51});
 

 c、通过update删除数据

1 String sql="delete from user where id=?";
2 jdbcTemplate.update(sql,51);
 

2、batchUpdate()批量插入、更新和删除方法
a、批量插入

1 String sql="insert into user (name,deptid) values (?,?)";

3 List<Object[]> batchArgs=new ArrayList<Object[]>();
4 batchArgs.add(new Object[]{"caoyc",6});
5 batchArgs.add(new Object[]{"zhh",8});
6 batchArgs.add(new Object[]{"cjx",8});

8 jdbcTemplate.batchUpdate(sql, batchArgs);


  batchUpdate方法第二参数是一个元素为Object[]数组类型的List集合

 

3、从数据中读取数据到实体对象
  先定一个User实体类

 

 1 package com.proc;
 2 
 3 public class User {
 4     private Integer id;
 5     private String name;
 6     private Integer deptid;
 7     public Integer getId() {
 8         return id;
 9     }
10     public void setId(Integer id) {
11         this.id = id;
12     }
13     public String getName() {
14         return name;
15     }
16     public void setName(String name) {
17         this.name = name;
18     }
19     public Integer getDeptid() {
20         return deptid;
21     }
22     public void setDeptid(Integer deptid) {
23         this.deptid = deptid;
24     }
25 
26     public String toString() {
27         return "User [id=" + id + ", name=" + name + ", deptid=" + deptid + "]";
28     }
29 }


 

 

a、读取单个对象

1 String sql="select id,name,deptid from user where id=?";

3 RowMapper<User> rowMapper=new BeanPropertyRowMapper<User>(User.class);
4 User user= jdbcTemplate.queryForObject(sql, rowMapper,52);
5 System.out.println(user);
  输出结果:

  User [id=52, name=caoyc, deptid=6]

 

【注意】:1、使用BeanProperytRowMapper要求sql数据查询出来的列和实体属性需要一一对应。如果数据中列明和属性名不一致,在sql语句中需要用as重新取一个别名

     2、使用JdbcTemplate对象不能获取关联对象

 

b、读取多个对象

1 String sql="select id,name,deptid from user";

3 RowMapper<User> rowMapper=new BeanPropertyRowMapper<User>(User.class);
4 List<User> users= jdbcTemplate.query(sql, rowMapper);
5 for (User user : users) {
6     System.out.println(user);
7 }


 

输出结果

...

User [id=49, name=姓名49, deptid=5]
User [id=50, name=姓名50, deptid=8]
User [id=52, name=caoyc, deptid=6]
User [id=53, name=zhh, deptid=8]
User [id=54, name=cjx, deptid=8]

---

 

c、获取某个记录某列或者count、avg、sum等函数返回唯一值

1 String sql="select count(*) from user";

3 int count= jdbcTemplate.queryForObject(sql, Integer.class);
4 System.out.println(count);
 

 

在实际开发中可以怎样用

UserDao.java

 1 package com.proc;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 5 import org.springframework.jdbc.core.JdbcTemplate;
 6 import org.springframework.jdbc.core.RowMapper;
 7 import org.springframework.stereotype.Repository;
 8 
 9 @Repository
10 public class UserDao {
11 
12     @Autowired
13     private JdbcTemplate jdbcTemplate;
14     
15     public User get(int id){
16         String sql="select id,name,deptid from user where id=?";
17         RowMapper<User> rowMapper=new BeanPropertyRowMapper<User>(User.class);
18         return jdbcTemplate.queryForObject(sql, rowMapper,id);
19     }
20 }


 

xml配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:aop="http://www.springframework.org/schema/aop"
 5     xmlns:context="http://www.springframework.org/schema/context"
 6     xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
 7         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 9 
10 <context:component-scan base-package="com.proc"></context:component-scan>
11 <context:property-placeholder location="classpath:db.properties"/>
12 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
13     <property name="user" value="${jdbc.user}"></property>
14     <property name="password" value="${jdbc.password}"></property>
15     <property name="driverClass" value="${jdbc.driverClass}"></property>
16     <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
17 </bean>
18 
19 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
20     <property name="dataSource" ref="dataSource"></property>
21 </bean>
22 </beans>


 

代码测试

1 UserDao userDao=(UserDao) ctx.getBean("userDao");
2 System.out.println(userDao.get(53));
我们不是制造者,我们是代码搬运工

 

 

一、首先配置JdbcTemplate;

要使用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 即可。提倡采用第三种方法。虽然下面的用法中采用了前两种方法

    

  配置方法有3种:

      1、

Java代码  

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

Xml代码  

<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>  
 

   方法2、

Java代码  

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

 spring配置文件为:

Xml代码  

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

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

Java代码  

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

spring配置文件:

 

Xml代码  

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

 

二、常用方法使用

【注意:】jdbcTemplate 中的sql均是用“?”做占位符的

domain User:

Java代码  

public class User {  
    private int id;  
    private String username;  
    private String password;  
    private String sex;  
              
               //setter和getter方法省略……  
}  
   

 

UserServiceImpl :

如果采用第三种方式,则下面的用法中将方法中的 jdbcTemplate 换成 this.getJdbcTemplate()即可。

 

Java代码  

     /**   
     * 创建表  
     */   
    public void create(String tableName){ //tb_test1  
        jdbcTemplate.execute("create table "+tableName +" (id integer,user_name varchar2(40),password varchar2(40))");  
    }  
      
    //jdbcTemplate.update适合于insert 、update和delete操作;  
    /**   
     * 第一个参数为执行sql   
     * 第二个参数为参数数据   
     */   
    public void save3(User user) {  
        Assert.isNull(user, "user is not null");  
        jdbcTemplate.update("insert into tb_test1(name,password) values(?,?)",   
                new Object[]{user.getUsername(),user.getPassword()});  
    }  
      
    /**   
     * 第一个参数为执行sql   
     * 第二个参数为参数数据   
     * 第三个参数为参数类型   
     */   
    @Override  
    public void save(User user) {  
        Assert.isNull(user, "user is not null");  
        jdbcTemplate.update(  
                "insert into tb_test1(name,password) values(?,?)",   
                new Object[]{user.getUsername(),user.getPassword()},   
                new int[]{java.sql.Types.VARCHAR,java.sql.Types.VARCHAR}  
                );  
    }  
  
    //避免sql注入  
    public void save2(final User user) {  
        Assert.isNull(user, "user is not null");  
          
        jdbcTemplate.update("insert into tb_test1(name,password) values(?,?)",   
                new PreparedStatementSetter(){  
              
                    @Override  
                    public void setValues(PreparedStatement ps) throws SQLException {  
                        ps.setString(1, user.getUsername());  
                        ps.setString(2, user.getPassword());  
                    }  
        });  
          
    }  
      
    public void save4(User user) {  
        Assert.isNull(user, "user is not null");  
        jdbcTemplate.update("insert into tb_test1(name,password) values(?,?)",   
                             new Object[]{user.getUsername(),user.getPassword()});  
    }  
      
    //返回插入的主键  
    public List save5(final User user) {  
          
        KeyHolder keyHolder = new GeneratedKeyHolder();  
  
        jdbcTemplate.update(new PreparedStatementCreator() {  
                      
                                @Override  
                                public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {  
                                    PreparedStatement ps = connection.prepareStatement("insert into tb_test1(name,password) values(?,?)", new String[] {"id"});  
                                    ps.setString(1, user.getUsername());  
                                    ps.setString(2, user.getPassword());  
                                    return ps;  
                                }  
                            },  
                keyHolder);  
          
        return keyHolder.getKeyList();  
    }  
      
    @Override  
    public void update(final User user) {  
        jdbcTemplate.update(  
                "update tb_test1 set name=?,password=? where id = ?",   
                new PreparedStatementSetter(){  
                    @Override  
                    public void setValues(PreparedStatement ps) throws SQLException {  
                        ps.setString(1, user.getUsername());  
                        ps.setString(2, user.getPassword());  
                        ps.setInt(3, user.getId());  
                    }  
                }  
        );  
    }  
  
    @Override  
    public void delete(User user) {  
        Assert.isNull(user, "user is not null");  
        jdbcTemplate.update(  
                "delete from tb_test1 where id = ?",   
                new Object[]{user.getId()},   
                new int[]{java.sql.Types.INTEGER});  
    }  
  
    @Deprecated //因为没有查询条件,所以用处不大  
    public int queryForInt1(){  
        return jdbcTemplate.queryForInt("select count(0) from tb_test1");  
    }  
      
    public int queryForInt2(User user){  
        return jdbcTemplate.queryForInt("select count(0) from tb_test1 where username = ?" ,  
                new Object[]{user.getUsername()});  
    }  
      
    //最全的参数3个  
    public int queryForInt3(User user){  
        return jdbcTemplate.queryForInt("select count(0) from tb_test1 where username = ?" ,  
                new Object[]{user.getUsername()},  
                new int[]{java.sql.Types.VARCHAR});  
    }  
      
    //可以返回是一个基本类型的值  
    @Deprecated  //因为没有查询条件,所以用处不大  
    public String queryForObject1(User user) {  
        return (String) jdbcTemplate.queryForObject("select username from tb_test1 where id = 100",  
                                                    String.class);  
    }  
      
    //可以返回值是一个对象  
    @Deprecated //因为没有查询条件,所以用处不大  
    public User queryForObject2(User user) {  
        return (User) jdbcTemplate.queryForObject("select * from tb_test1 where id = 100", User.class); //class是结果数据的java类型  
    }  
      
    @Deprecated //因为没有查询条件,所以用处不大  
    public User queryForObject3(User user) {  
        return (User) jdbcTemplate.queryForObject("select * from tb_test1 where id = 100",   
                    new RowMapper(){  
      
                        @Override  
                        public Object mapRow(ResultSet rs, int rowNum)throws SQLException {  
                            User user  = new User();  
                            user.setId(rs.getInt("id"));  
                            user.setUsername(rs.getString("username"));  
                            user.setPassword(rs.getString("password"));  
                            return user;  
                        }  
                    }  
        );   
    }  
      
    public User queryForObject4(User user) {  
        return (User) jdbcTemplate.queryForObject("select * from tb_test1 where id = ?",   
                                                    new Object[]{user.getId()},  
                                                    User.class); //class是结果数据的java类型  实际上这里是做反射,将查询的结果和User进行对应复制  
    }  
      
    public User queryForObject5(User user) {  
        return (User) jdbcTemplate.queryForObject(  
                "select * from tb_test1 where id = ?",   
                new Object[]{user.getId()},  
                new RowMapper(){  
  
                    @Override  
                    public Object mapRow(ResultSet rs,int rowNum)throws SQLException {  
                        User user  = new User();  
                        user.setId(rs.getInt("id"));  
                        user.setUsername(rs.getString("username"));  
                        user.setPassword(rs.getString("password"));  
                        return user;  
                    }  
              
        }); //class是结果数据的java类型  
    }  
      
    @Override  
    public User queryForObject(User user) {  
        //方法有返回值  
        return (User) jdbcTemplate.queryForObject("select * from tb_test1 where id = ?",  
                new Object[]{user.getId()},  
                new int[]{java.sql.Types.INTEGER},   
                new RowMapper() {  
              
                    @Override  
                    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {  
                        User user  = new User();  
                        user.setId(rs.getInt("id"));  
                        user.setUsername(rs.getString("username"));  
                        user.setPassword(rs.getString("password"));  
                        return user;  
                    }  
                }  
        );  
    }  
  
    @SuppressWarnings("unchecked")  
    public List<User> queryForList1(User user) {  
        return (List<User>) jdbcTemplate.queryForList("select * from tb_test1 where username = ?",   
                            new Object[]{user.getUsername()},  
                            User.class);  
    }  
  
    @SuppressWarnings("unchecked")  
    public List<String> queryForList2(User user) {  
        return (List<String>) jdbcTemplate.queryForList("select username from tb_test1 where sex = ?",   
                            new Object[]{user.getSex()},  
                            String.class);  
    }  
      
    @SuppressWarnings("unchecked")  
    //最全的参数查询  
    public List<User> queryForList3(User user) {  
        return (List<User>) jdbcTemplate.queryForList("select * from tb_test1 where username = ?",  
                            new Object[]{user.getUsername()},  
                            new int[]{java.sql.Types.VARCHAR},  
                            User.class);  
    }  
  
    //通过RowCallbackHandler对Select语句得到的每行记录进行解析,并为其创建一个User数据对象。实现了手动的OR映射。  
    public User queryUserById4(String id){  
        final User user  = new User();  
          
        //该方法返回值为void  
        this.jdbcTemplate.query("select * from tb_test1 where id = ?",   
                new Object[] { id },   
                new RowCallbackHandler() {     
              
                    @Override    
                    public void processRow(ResultSet rs) throws SQLException {     
                        User user  = new User();  
            user.setId(rs.getInt("id"));  
            user.setUsername(rs.getString("username"));  
            user.setPassword(rs.getString("password"));    
                    }     
        });   
          
        return user;     
    }  
      
    @SuppressWarnings("unchecked")  
    @Override  
    public List<User> list(User user) {  
        return jdbcTemplate.query("select * from tb_test1 where username like '%?%'",   
                new Object[]{user.getUsername()},   
                new int[]{java.sql.Types.VARCHAR},   
                new RowMapper(){  
              
                    @Override  
                    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {  
                        User user  = new User();  
                        user.setId(rs.getInt("id"));  
                        user.setUsername(rs.getString("username"));  
                        user.setPassword(rs.getString("password"));  
                        return user;  
                    }  
        });  
    }  
  
    //批量操作    适合于增、删、改操作  
    public int[] batchUpdate(final List users) {  
          
        int[] updateCounts = jdbcTemplate.batchUpdate(  
                "update tb_test1 set username = ?, password = ? where id = ?",  
                new BatchPreparedStatementSetter() {  
                      
                        @Override  
                        public void setValues(PreparedStatement ps, int i) throws SQLException {  
                            ps.setString(1, ((User)users.get(i)).getUsername());  
                            ps.setString(2, ((User)users.get(i)).getPassword());  
                            ps.setLong(3, ((User)users.get(i)).getId());  
                        }  
                          
                        @Override  
                        public int getBatchSize() {  
                            return users.size();  
                        }  
                }   
        );  
          
        return updateCounts;  
    }  
      
    //调用存储过程  
    public void callProcedure(int id){  
        this.jdbcTemplate.update("call SUPPORT.REFRESH_USERS_SUMMARY(?)", new Object[]{Long.valueOf(id)});  
}  
 

其中,batchUpdate适合于批量增、删、改操作;

         update(…):使用于增、删、改操作;

         execute():执行一个独立的sql语句,包括ddl语句;

         queryForInt :查询出一个整数值
--------------------- 

 

 

 


转载自:https://blog.csdn.net/qmdweb/article/details/81224330 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/HD243608836/article/details/85259375

智能推荐

如何判断一段程序是由C++编译还是C编译-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏12次。(1)如果是要你的代码在编译时就发现编译器类型,就判断_cplusplus或_STDC_宏,如果是一个C文件被编译,那么_STDC_就会被定义,_STDC_是预定义宏,当它被定义后,编译器将按照ANSIC标准来编译C语言程序。通常许多编译器还有其他编译标志宏。#ifdef __cpluspluscout<<"c++";#elsecout&l..._判断一段程序是由c

解决ASP.NET Web Applicatio超时时间已到.在操作完成之前超时时间已过或服务器未响应_using sqlconnection getconnection(-程序员宅基地

文章浏览阅读3k次。“超时时间已到。在操作完成之前超时时间已过或服务器未响应”初步分析原因为对MSSQL操作时连接超时,知道这事,以前没留意,大概是在配置文件中设置连接时限,在网上找了下解决方法,大多说在数据库连接字符串里解决SqlConnection con = new SqlConnection("server=.;database=myDB;uid=sa;pwd=password;")改为:_using sqlconnection getconnection(

Docker Compose+nginx实现负载均衡_docker-compose nginx 负载均衡-程序员宅基地

文章浏览阅读4.3k次。Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 前言本篇文章引导你使用Docker Compose在Docker容器中运行nginx和两个简单的Spring Boot应用程序,从而实现负载均衡。关于Docker 入门请参考纯洁的微笑Dock_docker-compose nginx 负载均衡

【Echarts】echarts tooltip小箭头,及阴影样式修改,双Y轴显示,折线图和柱状图同时展示,legend分开展示_echarts tooltip 箭头-程序员宅基地

文章浏览阅读7k次。this.circleChart = { tooltip: { trigger: 'item', backgroundColor: '#fff', textStyle: { color: '#666', ..._echarts tooltip 箭头

java scriptengine,使用Java ScriptEngine(Groovy),如何使它更具性能?-程序员宅基地

文章浏览阅读1.1k次。I am using ScriptEngine in my app to evaluate some client code in my application.The problem is it's not performant enough and I need to take measures to improve the time of execution.Currently, it ca..._scriptenginemanager 性能优化

msys2 环境配置记录-程序员宅基地

文章浏览阅读968次。命令行添加镜像地址首次安装后,配置软件源sed -i "1iServer = http://mirrors.ustc.edu.cn/msys2/mingw/i686" /etc/pacman.d/mirrorlist.mingw32sed -i "1iServer = http://mirrors.ustc.edu.cn/msys2/mingw/x86_64" /etc/pacma...

随便推点

WOW角色换装-程序员宅基地

文章浏览阅读136次。WOW的模型换装系统从一开始建模就经过很多的考虑,最大的可能将游戏人物的制作达到代码和资源的分离。让美工人员可以独立完成模型的制作。制作WOW的玩家模型工作量要远远大于制作普通的怪物模型。工作量增加的主要原因就是角色模型具有换装系统。普通模型身体各部分只做一份即可,而人物角色要做很多份,比如人物身上的披风可能要做不同的几个MESH,手套也要做好几个样式的,同理还是帽子,靴子,内..._换装大佬的博客

【链表】C++链表反转、链表逆序打印_逆序输出链表c++-程序员宅基地

文章浏览阅读740次。转载地址:http://blog.csdn.net/yebanxin/article/details/51942598题目:C++实现链表逆序打印、链表反转如何将链表逆序,取决于题目的要求。如果面试官只要求打印,一般不改动链表结构为好,如果要求改变链表的方向,则需要改变结构,再顺序打印。方法1:只逆序打印,不改变结构。采用递归,到达尾结点时打印输出,否则进入下一个结点的递归,当递归一层_逆序输出链表c++

C语言版数据结构- C语言实现栈,含详细的源代码_c语言栈源码-程序员宅基地

文章浏览阅读331次。SqStack.h 头文件#include <stdio.h> #include <stdlib.h> //函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 //定义函数返回的类型 typedef int Status; #define STACK_INIT_SIZ._c语言栈源码

目标检测中的数据增强方法及其实现_np.fliplr 数据增强-程序员宅基地

文章浏览阅读5.1k次,点赞5次,收藏68次。不同于图像分类中的数据增强,在目标检测中,由于涉及到了边界框(bounding box),导致有一些常用的图像增强不能用,在图像变化的时候同时要考虑到方框坐标点的变化。下面我们总结一些常用的包装好的数据增强函数。1、图像数组翻转 def random_flip(self, im, boxes): if random.random() < 0.5: ..._np.fliplr 数据增强

前端面试题1(html)-程序员宅基地

文章浏览阅读607次。HTML * Doctype作用?严格模式与混杂模式如何区分?它们有何意义?1.<!DOCTYPE> 声明位于文档中的最前面的位置,处于 <html> 标签之前。此标签可告知浏览器文档使用哪种 HTML 或 XHTML 规范2. 所谓的标准模式是指,浏览器按 W3C 标准解析执行代码;怪异模式则是使用浏览器自己的方式解析执行代码,因为不同浏览..._html 面试题

选项卡:选择一个按钮改变div的背景颜色_点击修改颜色按钮,输入颜色,修改div背景颜色-程序员宅基地

文章浏览阅读1.2k次。<!-- 选项卡:选择一个按钮改变div的背景颜色1. 获取三个button按钮和一个div2. 最先给div设置基本背景颜色3. 3个button设置onclick事件4. 点击按钮之后,div.style.cssText={background-color:选定颜色}--><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta _点击修改颜色按钮,输入颜色,修改div背景颜色