前段时间由于工作原因,需要编写一个制造测试数据(mysql)的工具类,网上搜了下,说JdbcTemplate不错,于是乎就准备使用下。为方便调用者无需了解JdbcTemplate,于是在此之上封装了一层,分别实现了增、删、查,且可批量操作,在封装批量新增方法时,费了点劲,最后用反射实现的。代码如下:
接口DataBaseDAO:
package com.wb.hz.test.util;
import java.util.List;
public interface DataBaseDAO {
public void delete(String tableName,String fieldName,Object id);
public void delete(String tableName,String fieldName,List<?> ids);
public int statisticsById(String tableName,String fieldName,Object id);
public <T> List<?> queryById(String tableName, String fieldName, Object id,boolean desc);
public <T> List<?> queryByIds(String tableName,String fieldName,Object startid,Object endid,boolean desc);
public <T> void insert(String sql,List<T> list);
}
实现类DataBaseDAOImpl:
package com.wb.hz.test.util.impl;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import com.wb.hz.test.util.DataBaseDAO;
@Repository
public class DataBaseDAOImpl implements DataBaseDAO {
@Resource
private JdbcTemplate jdbcTemplate;
public void delete(String tableName, String fieldName, Object id) {
String sql="delete from "+tableName+" where "+fieldName+"=?";
jdbcTemplate.update(sql, id);
}
public void delete(String tableName, String fieldName, List<?> ids) {
String sql="delete from "+tableName+" where "+fieldName+"=?";
for(int i=0;i<ids.size();i++){
jdbcTemplate.update(sql, ids.get(i));
}
}
public <T> List<Map<String,Object>> queryById(String tableName, String fieldName, Object ids, boolean desc) {
String sql="select * from "+tableName+" where "+fieldName+"="+String.valueOf(ids);
if(desc==true){
sql=sql+" order by id desc";
}
List<Map<String,Object>> list=jdbcTemplate.queryForList(sql);
return list;
}
public int statisticsById(String tableName,String fieldName ,Object id) {
String sql="select count(*) from "+tableName+" where "+fieldName+"="+String.valueOf(id);
int num=jdbcTemplate.queryForInt(sql);
return num;
}
public <T> List<?> queryByIds(String tableName,String fieldName, Object startid, Object endid,boolean desc) {
String sql="select * from "+tableName+" where "+fieldName+" >= "+String.valueOf(startid)+"and "+fieldName+" <= "+String.valueOf(endid);
if(desc==true){
sql=sql+" order by id desc";
}
List<Map<String, Object>> list=jdbcTemplate.queryForList(sql);
return list;
}
public <T> void insert(String sql, List<T> objlist) {
final List<T> list=objlist;
BatchPreparedStatementSetter setter=new BatchPreparedStatementSetter(){
public int getBatchSize(){
return list.size();
}
public void setValues(PreparedStatement ps,int index) throws SQLException{
T t=list.get(index);
Field fields[]=t.getClass().getDeclaredFields();
try {
for(int i=0;i<fields.length;i++){
PropertyDescriptor prop=new PropertyDescriptor(fields[i].getName(),t.getClass());
Method getmethod=prop.getReadMethod();
if(fields[i].getType().getCanonicalName().equalsIgnoreCase("java.lang.String")){
ps.setString(i+1, String.valueOf(getmethod.invoke(t)));
//System.out.println(ps.getResultSet().getString(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("int")){
ps.setInt(i+1, (Integer)getmethod.invoke(t));
//System.out.println(ps.getResultSet().getInt(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("long")){
ps.setLong(i+1, (Long) getmethod.invoke(t));
//System.out.println(ps.getResultSet().getLong(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("double")){
ps.setDouble(i+1, (Double) getmethod.invoke(t));
//System.out.println(ps.getResultSet().getDouble(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("java.lang.Integer")){
ps.setInt(i+1, (Integer)getmethod.invoke(t));
//System.out.println(ps.getResultSet().getInt(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("java.lang.Long")){
ps.setLong(i+1, (Long) getmethod.invoke(t));
//System.out.println(ps.getResultSet().getLong(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("java.lang.Double")){
ps.setDouble(i+1, (Double) getmethod.invoke(t));
//System.out.println(ps.getResultSet().getDouble(i+1));
}
else if(fields[i].getType().getCanonicalName().equalsIgnoreCase("java.util.Date")){
ps.setDate(i+1, new java.sql.Date(((Date)getmethod.invoke(t)).getTime()));
//System.out.println(ps.getResultSet().getDate(i+1));
}
}
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IntrospectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
jdbcTemplate.batchUpdate(sql,setter);
}
}
写完后,试验了一下,这些方法都没问题!于是被当做工具类使用,谁知刚用没多久,问题曝露了,对某表调用批量新增方法插入数据报错,提示某个值对应的字段不对,可是这个字段值实际对应的字段并非异常中显示的,初步判断肯定是字段映射出了问题,重新检查了java反射的那段代码,发现没问题呀!于是冷静分析,决定从头排查,发现传入的sql语句为:insert into tablename values(?,?,?,?,?,?,?); tablename后没有写明字段,于是根据传入的vo对象中定义的字段属性的顺序将这些字段对应的表中字段名写入sql,再次执行,不报错了!看来实现类还需要去解析表字段并将传入的对象属性进行映射才能避免这种情况发生,否则这个方法非常不智能啊!
分享到:
相关推荐
首先,要使用`JdbcTemplate`,我们需要添加Spring的支持。这通常意味着在项目中引入Spring的相关库,比如`spring-jdbc.jar`,并且在项目配置中声明Spring的依赖管理。这可以通过Maven或Gradle等构建工具完成。 接...
配制Spring事务和JdbcTemplate使用 配制Spring事务和JdbcTemplate使用
**Spring JdbcTemplate 使用指南** Spring框架中的JdbcTemplate是数据库操作的核心组件之一,它提供了一种简单、安全的方式来执行SQL查询和更新,而无需手动管理数据库连接。本指南将深入探讨JdbcTemplate的用法,...
以下是对JdbcTemplate使用的一些详细说明: 1. **创建表和执行SQL语句**: JdbcTemplate的`execute()`方法可以用来执行任意的SQL语句,包括DDL(数据定义语言)如创建表。在示例中,`execute()`方法被用来创建名为...
本文将深入探讨如何使用`JdbcTemplate`配合游标滚动来解决分页问题,并结合提供的两个文件`JdbcTemplateExtend.java`和`SplitPageResultSetExtractor.java`进行讲解。 首先,我们需要理解什么是游标滚动。在数据库...
使用Spring的JdbcTemplate实现分页功能
在 Spring 中使用 `JdbcTemplate` 需要以下几个步骤: 1. **配置数据源**:Spring 通过数据源(DataSource)与数据库建立连接。在这个例子中,我们将使用 c3p0 数据源。c3p0 是一个开源的 JDBC 连接池,它可以提供...
使用JdbcTemplate可以使得代码更加简洁,更易于测试和维护。 2. **JdbcTemplate的依赖注入** 在Spring配置文件中,我们需要定义一个JdbcTemplate bean,并注入DataSource。DataSource是数据库连接池的实例,负责...
jdbcTemplate使用方法实例解析 jdbcTemplate是一个基于Spring JDBC抽象框架的核心类,提供了大量实用的方法来简化数据库操作。在本文中,我们将详细介绍jdbcTemplate的使用方法实例解析,以及其在实际开发中的应用...
`JdbcUtils.java`可能是提供了一些数据库连接和JdbcTemplate使用的辅助方法,如数据库连接池的配置,或者封装了JdbcTemplate的执行方法,以提高代码复用性。例如: ```java public class JdbcUtils { private ...
在这个场景中,我们将详细探讨如何使用`JdbcTemplate`进行批量插入和删除操作。 批量插入操作在数据库处理大量数据时非常常见,它可以显著提高性能,因为数据库通常会优化批量处理,而不是单独处理每一项。在提供的...
JdbcTemplate使用PreparedStatement来执行SQL,自动防止SQL注入攻击,因为它会正确地转义参数值。 7. 错误处理 如果数据库操作失败,JdbcTemplate会抛出异常,如`DataAccessException`,使得我们可以快速定位并处理...
通过使用`JdbcTemplate`,开发者可以编写出更简洁、更健壮的数据库访问代码,因为它会自动处理资源关闭、异常转换等细节。 `SimpleJdbcTemplate`是`JdbcTemplate`的一个简化版本,提供了一种更方便的构造函数来初始...
本篇文章将详细讲解`jdbcTemplate`的预编译使用,以及如何通过回调方法进行定制化的数据处理。 首先,`jdbcTemplate`的核心功能是通过预编译的SQL语句(PreparedStatement)来执行数据库操作。预编译SQL可以有效...
在本教程中,我们将深入探讨如何在Spring Boot项目中配置和使用多数据源以及JdbcTemplate。 首先,让我们了解什么是`JdbcTemplate`。它是Spring提供的一种模板类,用于执行SQL语句,通过回调机制将结果转换为Java...
使用JdbcTemplate的基本步骤如下: 1. **配置数据源(DataSource)**:通常我们会使用连接池如DruidDataSource来管理数据库连接。这需要引入相关依赖并配置数据源的相关属性。 2. **创建JdbcTemplate实例**:通过...
这篇博客文章的标题"打印JdbcTemplate执行sql"主要涉及如何在使用`JdbcTemplate`时,追踪并打印出执行的SQL语句,这对于调试和性能分析非常有帮助。接下来,我们将深入探讨`JdbcTemplate`的工作原理以及如何实现SQL...
首先,要使用JdbcTemplate,我们需要在SpringBoot项目中引入相关的依赖。这里使用了阿里巴巴的Druid数据源(com.alibaba.druid-spring-boot-starter)以及MySQL的驱动(mysql-connector-java)。Druid是一个优秀的...
例如,大量数据的批量插入可能更适合使用JdbcTemplate的`batchUpdate()`方法,或者直接使用JDBC的PreparedStatement来提高效率。 9. **最佳实践** - 保持SQL语句简洁,避免在业务代码中混杂复杂的SQL。 - 避免...