基于SpringJdbc的泛型Dao

使用的Spring是3.1版本,不是3.0版本。两者还是有区别的,其中一点就是:SimpleJdbcTemplate在3.1版本被标记为过时了,而SimpleJdbcTemplate的一些方法,被JdbcTemplate吸收了。所以,个人推荐使用3.1版本.

 

 

需要的JAR文件:

 

org.springframework.aop-3.1.0.RELEASE.jar

org.springframework.asm-3.1.0.RELEASE.jar

org.springframework.beans-3.1.0.RELEASE.jar

org.springframework.context-3.1.0.RELEASE.jar

org.springframework.core-3.1.0.RELEASE.jar

org.springframework.expression-3.1.0.RELEASE.jar

org.springframework.jdbc-3.1.0.RELEASE.jar

org.springframework.test-3.1.0.RELEASE.jar

org.springframework.transaction-3.1.0.RELEASE.jar

 

com.springsource.net.sf.cglib-2.2.0.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

com.springsource.org.apache.commons.logging-1.1.1.jar

com.springsource.org.junit-4.7.0.jar

 

ojdbc14.jar

 

数据库脚本:

--创建商品表
create table product(
	id		varchar2(255)	primary key,
	name		varchar2(255),
	author    	 	varchar2(255),
	price		number(6,2),
	quantity   	number,
	description	varchar2(255)
);

 

 

实体类:

package org.monday.springjdbc.domain;


public class Product /*implements Serializable*/{ //暂不序列化

	private String id;
	private String name;
	private String author;
	private double price;
	private int quantity;
	private String description;

	public Product() {

	}

	// getter and setter

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + ", author=" + author + ", price=" + price + ", quantity="
				+ quantity + ", description=" + description + "]\n";
	}
}

 

 

正题:

 

BaseDao接口不提供了,附件中会有,直接给出BaseDaoImpl

 

package org.monday.springjdbc.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.Types;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.monday.springjdbc.dao.BaseDao;
import org.monday.springjdbc.util.QueryResult;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

/**
 * 使用场景
 * 
 * 数据库是Oracle
 * 主键列名为id
 * 主键由程序提供(这里用的是UUID)
 * 实体类名和数据库表名一致  比如:类名Product 表名product、PRODUCT、Produc 都可以 t_product 不可以
 */
public class BaseDaoImpl<T> implements BaseDao<T> {

	/** 设置一些操作的常量 */
	public static final String SQL_INSERT = "insert";
	public static final String SQL_UPDATE = "update";
	public static final String SQL_DELETE = "delete";

	private JdbcTemplate jdbcTemplate;

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	private Class<T> entityClass;

	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
		entityClass = (Class<T>) type.getActualTypeArguments()[0];
		System.out.println("Dao实现类是:" + entityClass.getName());
	}

	@Override
	public void save(T entity) {
		String sql = this.makeSql(SQL_INSERT);
		Object[] args = this.setArgs(entity, SQL_INSERT);
		int[] argTypes = this.setArgTypes(entity, SQL_INSERT);
		jdbcTemplate.update(sql.toString(), args, argTypes);
	}

	@Override
	public void update(T entity) {
		String sql = this.makeSql(SQL_UPDATE);
		Object[] args = this.setArgs(entity, SQL_UPDATE);
		int[] argTypes = this.setArgTypes(entity, SQL_UPDATE);
		jdbcTemplate.update(sql, args, argTypes);
	}

	@Override
	public void delete(T entity) {
		String sql = this.makeSql(SQL_DELETE);
		Object[] args = this.setArgs(entity, SQL_DELETE);
		int[] argTypes = this.setArgTypes(entity, SQL_DELETE);
		jdbcTemplate.update(sql, args, argTypes);
	}

	@Override
	public void delete(Serializable id) {
		String sql = " DELETE FROM " + entityClass.getSimpleName() + " WHERE id=?";
		jdbcTemplate.update(sql, id);
	}

	@Override
	public void deleteAll() {
		String sql = " TRUNCATE TABLE " + entityClass.getSimpleName();
		jdbcTemplate.execute(sql);
	}

	/**
	 * 未完成
	 */
	@Override
	public void batchSave(List<T> list) {

	}

	/**
	 * 未完成
	 */
	@Override
	public void batchUpdate(List<T> list) {

	}

	/**
	 * 未完成
	 */
	@Override
	public void batchDelete(List<T> list) {

	}

	@Override
	public T findById(Serializable id) {
		String sql = "SELECT * FROM " + entityClass.getSimpleName() + " WHERE id=?";
		RowMapper<T> rowMapper = BeanPropertyRowMapper.newInstance(entityClass);
		return jdbcTemplate.query(sql, rowMapper, id).get(0);
	}

	@Override
	public List<T> findAll() {
		String sql = "SELECT * FROM " + entityClass.getSimpleName();
		RowMapper<T> rowMapper = BeanPropertyRowMapper.newInstance(entityClass);
		return jdbcTemplate.query(sql, rowMapper);
	}

	@Override
	public QueryResult<T> findByPage(int pageNo, int pageSize) {
		List<T> list = this.find(pageNo, pageSize, null, null);
		int totalRow = this.count(null);
		return new QueryResult<T>(list, totalRow);
	}

	@Override
	public QueryResult<T> findByPage(int pageNo, int pageSize, Map<String, String> where) {
		List<T> list = this.find(pageNo, pageSize, where, null);
		int totalRow = this.count(where);
		return new QueryResult<T>(list, totalRow);
	}

	@Override
	public QueryResult<T> findByPage(int pageNo, int pageSize, LinkedHashMap<String, String> orderby) {
		List<T> list = this.find(pageNo, pageSize, null, orderby);
		int totalRow = this.count(null);
		return new QueryResult<T>(list, totalRow);
	}

	@Override
	public QueryResult<T> findByPage(int pageNo, int pageSize, Map<String, String> where,
			LinkedHashMap<String, String> orderby) {
		List<T> list = this.find(pageNo, pageSize, where, orderby);
		int totalRow = this.count(where);
		return new QueryResult<T>(list, totalRow);
	}

	// 组装SQL
	private String makeSql(String sqlFlag) {
		StringBuffer sql = new StringBuffer();
		Field[] fields = entityClass.getDeclaredFields();
		if (sqlFlag.equals(SQL_INSERT)) {
			sql.append(" INSERT INTO " + entityClass.getSimpleName());
			sql.append("(");
			for (int i = 0; fields != null && i < fields.length; i++) {
				fields[i].setAccessible(true); // 暴力反射
				String column = fields[i].getName();
				sql.append(column).append(",");
			}
			sql = sql.deleteCharAt(sql.length() - 1);
			sql.append(") VALUES (");
			for (int i = 0; fields != null && i < fields.length; i++) {
				sql.append("?,");
			}
			sql = sql.deleteCharAt(sql.length() - 1);
			sql.append(")");
		} else if (sqlFlag.equals(SQL_UPDATE)) {
			sql.append(" UPDATE " + entityClass.getSimpleName() + " SET ");
			for (int i = 0; fields != null && i < fields.length; i++) {
				fields[i].setAccessible(true); // 暴力反射
				String column = fields[i].getName();
				if (column.equals("id")) { // id 代表主键
					continue;
				}
				sql.append(column).append("=").append("?,");
			}
			sql = sql.deleteCharAt(sql.length() - 1);
			sql.append(" WHERE id=?");
		} else if (sqlFlag.equals(SQL_DELETE)) {
			sql.append(" DELETE FROM " + entityClass.getSimpleName() + " WHERE id=?");
		}
		System.out.println("SQL=" + sql);
		return sql.toString();

	}

	// 设置参数
	private Object[] setArgs(T entity, String sqlFlag) {
		Field[] fields = entityClass.getDeclaredFields();
		if (sqlFlag.equals(SQL_INSERT)) {
			Object[] args = new Object[fields.length];
			for (int i = 0; args != null && i < args.length; i++) {
				try {
					fields[i].setAccessible(true); // 暴力反射
					args[i] = fields[i].get(entity);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return args;
		} else if (sqlFlag.equals(SQL_UPDATE)) {
			Object[] tempArr = new Object[fields.length];
			for (int i = 0; tempArr != null && i < tempArr.length; i++) {
				try {
					fields[i].setAccessible(true); // 暴力反射
					tempArr[i] = fields[i].get(entity);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			Object[] args = new Object[fields.length];
			System.arraycopy(tempArr, 1, args, 0, tempArr.length - 1); // 数组拷贝
			args[args.length - 1] = tempArr[0];
			return args;
		} else if (sqlFlag.equals(SQL_DELETE)) {
			Object[] args = new Object[1]; // 长度是1
			fields[0].setAccessible(true); // 暴力反射
			try {
				args[0] = fields[0].get(entity);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return args;
		}
		return null;

	}

	// 设置参数类型(写的不全,只是一些常用的)
	private int[] setArgTypes(T entity, String sqlFlag) {
		Field[] fields = entityClass.getDeclaredFields();
		if (sqlFlag.equals(SQL_INSERT)) {
			int[] argTypes = new int[fields.length];
			try {
				for (int i = 0; argTypes != null && i < argTypes.length; i++) {
					fields[i].setAccessible(true); // 暴力反射
					if (fields[i].get(entity).getClass().getName().equals("java.lang.String")) {
						argTypes[i] = Types.VARCHAR;
					} else if (fields[i].get(entity).getClass().getName().equals("java.lang.Double")) {
						argTypes[i] = Types.DECIMAL;
					} else if (fields[i].get(entity).getClass().getName().equals("java.lang.Integer")) {
						argTypes[i] = Types.INTEGER;
					} else if (fields[i].get(entity).getClass().getName().equals("java.util.Date")) {
						argTypes[i] = Types.DATE;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return argTypes;
		} else if (sqlFlag.equals(SQL_UPDATE)) {
			int[] tempArgTypes = new int[fields.length];
			int[] argTypes = new int[fields.length];
			try {
				for (int i = 0; tempArgTypes != null && i < tempArgTypes.length; i++) {
					fields[i].setAccessible(true); // 暴力反射
					if (fields[i].get(entity).getClass().getName().equals("java.lang.String")) {
						tempArgTypes[i] = Types.VARCHAR;
					} else if (fields[i].get(entity).getClass().getName().equals("java.lang.Double")) {
						tempArgTypes[i] = Types.DECIMAL;
					} else if (fields[i].get(entity).getClass().getName().equals("java.lang.Integer")) {
						tempArgTypes[i] = Types.INTEGER;
					} else if (fields[i].get(entity).getClass().getName().equals("java.util.Date")) {
						tempArgTypes[i] = Types.DATE;
					}
				}
				System.arraycopy(tempArgTypes, 1, argTypes, 0, tempArgTypes.length - 1); // 数组拷贝
				argTypes[argTypes.length - 1] = tempArgTypes[0];

			} catch (Exception e) {
				e.printStackTrace();
			}
			return argTypes;

		} else if (sqlFlag.equals(SQL_DELETE)) {
			int[] argTypes = new int[1]; // 长度是1
			try {
				fields[0].setAccessible(true); // 暴力反射
				if (fields[0].get(entity).getClass().getName().equals("java.lang.String")) {
					argTypes[0] = Types.VARCHAR;
				} else if (fields[0].get(entity).getClass().getName().equals("java.lang.Integer")) {
					argTypes[0] = Types.INTEGER;
				}

			} catch (Exception e) {
				e.printStackTrace();
			}
			return argTypes;
		}
		return null;
	}

	private List<T> find(int pageNo, int pageSize, Map<String, String> where, LinkedHashMap<String, String> orderby) {
		// where 与 order by 要写在select * from table 的后面,而不是where rownum<=? ) where rn>=?的后面
		StringBuffer sql = new StringBuffer(" SELECT * FROM (SELECT t.*,ROWNUM rn FROM (SELECT * FROM "
				+ entityClass.getSimpleName());
		if (where != null && where.size() > 0) {
			sql.append(" WHERE "); // 注意不是where
			for (Map.Entry<String, String> me : where.entrySet()) {
				String columnName = me.getKey();
				String columnValue = me.getValue();
				sql.append(columnName).append(" ").append(columnValue).append(" AND "); // 没有考虑or的情况
			}
			int endIndex = sql.lastIndexOf("AND");
			if (endIndex > 0) {
				sql = new StringBuffer(sql.substring(0, endIndex));
			}
		}
		if (orderby != null && orderby.size() > 0) {
			sql.append(" ORDER BY ");
			for (Map.Entry<String, String> me : orderby.entrySet()) {
				String columnName = me.getKey();
				String columnValue = me.getValue();
				sql.append(columnName).append(" ").append(columnValue).append(",");
			}
			sql = sql.deleteCharAt(sql.length() - 1);
		}
		sql.append(" ) t WHERE ROWNUM<=? ) WHERE rn>=? ");
		System.out.println("SQL=" + sql);
		Object[] args = { pageNo * pageSize, (pageNo - 1) * pageSize + 1 };
		RowMapper<T> rowMapper = BeanPropertyRowMapper.newInstance(entityClass);
		return jdbcTemplate.query(sql.toString(), args, rowMapper);
	}

	private int count(Map<String, String> where) {
		StringBuffer sql = new StringBuffer(" SELECT COUNT(*) FROM " + entityClass.getSimpleName());
		if (where != null && where.size() > 0) {
			sql.append(" WHERE ");
			for (Map.Entry<String, String> me : where.entrySet()) {
				String columnName = me.getKey();
				String columnValue = me.getValue();
				sql.append(columnName).append(" ").append(columnValue).append(" AND "); // 没有考虑or的情况
			}
			int endIndex = sql.lastIndexOf("AND");
			if (endIndex > 0) {
				sql = new StringBuffer(sql.substring(0, endIndex));
			}
		}
		System.out.println("SQL=" + sql);
		return jdbcTemplate.queryForInt(sql.toString());
	}

}

 

其他具体的接口只要继承BaseDao就可以了

例如:

 

package org.chendl.springjdbc.dao;

import org.chendl.springjdbc.domain.Product;

public interface ProductDao extends BaseDao<Product> {

}

 

 

而具体的实现类只要集成BaseDaoImpl,并实现自己的接口就可以了。

例如:

package org.monday.springjdbc.dao.impl;
import org.monday.springjdbc.dao.ProductDao;
import org.monday.springjdbc.domain.Product;
public class ProductDaoImpl extends BaseDaoImpl<Product> implements ProductDao{

	
}

 

 

补上分页的工具类:

package org.monday.springjdbc.util;
import java.util.List;

public class QueryResult<T> {

	private List<T> list; // 结果集
	private int totalRow; // 总记录数

	public QueryResult() {
	}

	public QueryResult(List<T> list, int totalRow) {
		this.list = list;
		this.totalRow = totalRow;
	}

	//getter and setter

}

 

补上生成主键的工具类:

package org.monday.springjdbc.util;
import java.util.UUID;

public final class ToolUtil {

	/**
	 * 生成32位UUID 并去掉"-"
	 */
	public static String getUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	public static void main(String[] args) {
		System.out.println(ToolUtil.getUUID());
		System.out.println(ToolUtil.getUUID().length());// 32
	}
}

 

 

Spring的配置文件Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-3.1.xsd
						http://www.springframework.org/schema/aop 
						http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
						
	<!-- 加载属性文件 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>					

	<!-- 配置数据源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	
	<!-- 配置jdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- 配置Dao -->
 
 	<bean id="baseDao" class="org.monday.springjdbc.dao.impl.BaseDaoImpl" abstract="true">
 		<property name="jdbcTemplate" ref="jdbcTemplate"/>
 	</bean>
 	<bean id="productDao" class="org.monday.springjdbc.dao.impl.ProductDaoImpl" parent="baseDao"/>
 
	
	<!-- 配置事务 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*"/>
			<tx:method name="find*" read-only="true"/>
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut id="daoMethod" expression="execution(* org.monday.springjdbc.dao.impl.*Impl*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethod"/>
	</aop:config>

</beans>

 

 

测试:

 

1.测试Spring的数据源

package junit.test;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/beans.xml" })
public class SpringTest {

	// 测试是否取得数据库连接
	@Test
	public void testDataSource() throws SQLException {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		DataSource dataSource = ctx.getBean(DataSource.class);
		System.out.println(dataSource.getConnection());
	}
}

 

2.测试Dao

package junit.test;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.monday.springjdbc.dao.ProductDao;
import org.monday.springjdbc.domain.Product;
import org.monday.springjdbc.util.QueryResult;
import org.monday.springjdbc.util.ToolUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/beans.xml" })
public class BaseDaoTest {

	@Autowired
	private ProductDao dao;

	@Test
	public void testSave() throws Exception {
		Product product = new Product();
		product.setId(ToolUtil.getUUID());
		product.setName("aaa");
		product.setAuthor("bbb");
		product.setPrice(111);
		product.setQuantity(9);
		product.setDescription("ccc");
		dao.save(product);
	}

	@Test
	public void testUpdate() throws Exception {
		Product product = new Product();
		product.setId("79934cfd71b84cc6819d3c06b2984f80");
		product.setName("a");
		product.setAuthor("b");
		product.setPrice(444);
		product.setQuantity(44);
		product.setDescription("c");
		dao.update(product);
	}

	@Test
	public void testDelete1() {
		Product product = new Product();
		product.setId("79934cfd71b84cc6819d3c06b2984f80");
		dao.delete(product);
	}

	@Test
	public void testDelete2() {
		dao.delete("7030aaf8a19d4d30b26e6e2588c43c30");
	}

	@Test
	public void testDeleteAll() {
		dao.deleteAll();
	}

	// 插入一些测试数据
	@Test
	public void insertTestData() {
		for (int i = 1; i <= 100; i++) {
			Product product = new Product();
			product.setId(ToolUtil.getUUID());
			product.setName("springJdbc" + i);
			product.setAuthor("monday" + i);
			product.setPrice((double) Math.random() * 100);
			product.setQuantity((int) (Math.random() * 100));
			product.setDescription("介绍SpringJdbc" + i);
			dao.save(product);
		}
	}

	// 未完成
	@Test
	public void testBatchSave() {
	}

	// 未完成
	@Test
	public void testBatchUpdate() {
	}

	// 未完成
	@Test
	public void testBatchDelete() {
	}

	@Test
	public void testFindById() {
		System.out.println(dao.findById("07b5999dcb9346b3b353df18de345c31"));
	}

	@Test
	public void testFindAll() {
		System.out.println(dao.findAll());
	}

	// 分页
	@Test
	public void testFindByPage1() {
		int pageNo = 1;
		int pageSize = 10;
		QueryResult<Product> queryResult = dao.findByPage(pageNo, pageSize);
		for (Product p : queryResult.getList()) {
			System.out.println(p.getAuthor());
		}
	}

	// 分页+条件
	@Test
	public void testFindByPage2() {
		int pageNo = 1;
		int pageSize = 10;
		Map<String, String> where = new HashMap<String, String>();
		where.put("author", "like '%monday1%'");
		where.put("price", "<90");
		QueryResult<Product> queryResult = dao.findByPage(pageNo, pageSize, where);
		for (Product p : queryResult.getList()) {
			System.out.println(p.getAuthor());
		}
	}

	// 分页+排序
	@Test
	public void testFindByPage3() {
		int pageNo = 1;
		int pageSize = 10;
		LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>();
		orderby.put("price", "desc");
		orderby.put("author", "asc");
		QueryResult<Product> queryResult = dao.findByPage(pageNo, pageSize, orderby);
		for (Product p : queryResult.getList()) {
			System.out.println(p.getAuthor());
		}
	}

	// 分页+条件+排序
	@Test
	public void testFindByPage4() {
		int pageNo = 1;
		int pageSize = 10;
		Map<String, String> where = new HashMap<String, String>();
		where.put("author", "like '%monday1%'");
		where.put("price", "<90");
		LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>();
		orderby.put("price", "desc");
		orderby.put("author", "asc");
		QueryResult<Product> queryResult = dao.findByPage(pageNo, pageSize, where, orderby);
		for (Product p : queryResult.getList()) {
			System.out.println(p.getAuthor());
		}
	}
}

 

 

一些说明:

 

     这些代码的应用有些局限性,没有使用Hibernate方便。 可能还有些Bug自己没有测试出来。这里只是提供一些思路或者只是为了学习而用。之所以有这么想法是觉得单纯的使用JDBC确实有点那个(你懂的...),而使HibernateTemplate可以实现类似的Dao,那用SpringJdbc能吗?自己就试了试。就个人觉得SpringJdbc 是十分好用的。有一次写批量的时候,SpringJdbc提供的batchUpdate()方法比Hibernate的快好多。所以,就自己看来,持久层可以Hibernate+SpringJdbc搭配使用,其中批量建议使用SpringJdbc处理。(可能自己还没想到Hiberante批量性能提高的方法)。而这里基于SpringJdbc的泛型的批量方法,还没想出来。基于HibernateTemplate的倒是可以,但是性能...

这里只是自己一点学习心得仅供参考。

 

 

 

 

你可能感兴趣的:(DAO,SpringJDBC)