JdbcTemplate 动态创建表并添加数据
来源:互联网 发布:麒麟外推软件 编辑:程序博客网 时间:2024/05/16 10:26
之前写了一个 使用JDBC查询是否存在某表或视图,按月动态生成表 ,但是他并不能进行公用,使用时需要每个人都写自己的处理代码,为了方便使用,我写了一个公共的处理方法,仅供参考。
为了考虑大家项目的集成,获得JdbcTemplate我采用Spring配置,也为了方便大家直接运行,初始化Spring的方式是写的Main方法
主要思路是:
使用Spring配置JdbcTemplate
通过一个代理对象和数据库进行对应,这个对象除了id和一个tableName属性外和数据库的字段名称都是一致的
通过一个公共方法类来获得代理类有那些属性,用来创建表和新增时进行动态SQL的拼装
核心处理是,先看有么有该表,没有创建插入,有的话直接插入
首先配置Spring,大家都会的:
- <?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: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-2.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
- <!-- 数据源 -->
- <bean id="dataSource"
- class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <property name="driverClassName" value="com.mysql.jdbc.Driver" />
- <property name="url"
- value="jdbc:mysql://192.168.0.69:3306/cui?useUnicode=true&characterEncoding=UTF-8" />
- <property name="username" value="root" />
- <property name="password" value="root" />
- <!-- 连接池启动时的初始值 -->
- <property name="initialSize" value="2" />
- <!-- 连接池的最大值 -->
- <property name="maxActive" value="2" />
- <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
- <property name="maxIdle" value="2" />
- <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
- <property name="minIdle" value="2" />
- <property name="defaultAutoCommit" value="true" />
- </bean>
- <!-- JDBC 操作模板 -->
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <constructor-arg>
- <ref bean="dataSource"/>
- </constructor-arg>
- </bean>
- <!-- 用于初始化获得Spring对象的类 -->
- <bean id="springfactory" class="com.SpringFactory"></bean>
- </beans>
com.SpringFactory对象是用来动态获取Spring管理对象的类,之前博客中提到过:
- package com;
- import org.springframework.beans.BeansException;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- /**
- * @说明 获得Spring管理对象
- * @author cuisuqiang
- * @version 1.0
- * @since
- */
- public class SpringFactory implements ApplicationContextAware {
- private static ApplicationContext context;
- @SuppressWarnings("static-access")
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this.context = applicationContext;
- }
- public static Object getObject(String id) {
- Object object = null;
- object = context.getBean(id);
- return object;
- }
- }
这个类可以根据配置的对象ID来获得该对象的引用
我们还需要将参数中对象进行处理,获得对象的属性名称和对应的值,这里提供了一个公共方法,之前博客提到过,只是改动了一些:
- package com;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * @说明 对象操纵高级方法
- * @author cuisuqiang
- * @version 1.0
- * @since
- */
- public class ObjectUtil {
- /**
- * 返回一个对象的属性和属性值
- */
- @SuppressWarnings("unchecked")
- public static Map<String,String> getProperty(Object entityName) {
- Map<String,String> map = new HashMap<String, String>();
- try {
- Class c = entityName.getClass();
- // 获得对象属性
- Field field[] = c.getDeclaredFields();
- for (Field f : field) {
- Object v = invokeMethod(entityName, f.getName(), null);
- map.put(f.getName(), v.toString());
- }
- } catch (Exception e) {
- map = null;
- }
- return map;
- }
- /**
- * 获得对象属性的值
- */
- @SuppressWarnings("unchecked")
- private static Object invokeMethod(Object owner, String methodName,
- Object[] args) throws Exception {
- Class ownerClass = owner.getClass();
- methodName = methodName.substring(0, 1).toUpperCase()
- + methodName.substring(1);
- Method method = null;
- try {
- method = ownerClass.getMethod("get" + methodName);
- } catch (SecurityException e) {
- } catch (NoSuchMethodException e) {
- return " can't find 'get" + methodName + "' method";
- }
- return method.invoke(owner);
- }
- }
传递一个对象,就会返回该对象的属性和属性值的Map
再来看一下对象实体类,要注意这个类一定不要和实际的类混了,因为你的业务对象类中可能会有一些额外的字段,这个会被公共方法的类解析而出问题的
- package com;
- /**
- * @说明 需要操作的实体
- * @author cuisuqiang
- * @version 1.0
- * @since 这个只能是代理对象,也就是说你需要和数据库同步对属性字段,实际上我们在表中还动态添加了一个 tableName 字段
- */
- public class Users {
- private String userName;
- private String userPass;
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getUserPass() {
- return userPass;
- }
- public void setUserPass(String userPass) {
- this.userPass = userPass;
- }
- }
也就是说数据会有四个字段 id,userName,userPass,tableName,其中id和tableName是无需关心的
核心处理类我先发代码:
- package com;
- import java.sql.Connection;
- import java.sql.DatabaseMetaData;
- import java.sql.ResultSet;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Map;
- import java.util.Set;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import org.springframework.jdbc.core.JdbcTemplate;
- /**
- * @说明 进行测试
- * @author cuisuqiang
- * @version 1.0
- * @since
- */
- public class DbTest {
- private static ApplicationContext context = null;
- public static void main(String[] args) {
- context = new ClassPathXmlApplicationContext("applicationContext.xml");
- Users user = new Users();
- user.setUserName("cuisuqinag@163.com");
- user.setUserPass("http://cuisuqiang.iteye.com/");
- int re = insertObject("users",user);
- System.out.println("---->" + re + "<----");
- }
- public static int insertObject(String tableName,Object obj){
- int re = 0;
- try {
- JdbcTemplate jt = (JdbcTemplate)context.getBean("jdbcTemplate");
- SimpleDateFormat format = new SimpleDateFormat("yyyy_MM");
- String tname = tableName + "_" + format.format(new Date());
- // 如果有某表
- if(getAllTableName(jt,tname)){
- // 保存数据
- re = saveObj(jt,tname,obj);
- }else{
- // 动态创建表
- re = createTable(jt,tname,obj);
- // 保存数据
- re = saveObj(jt,tname,obj);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return re;
- }
- /**
- * 保存方法,注意这里传递的是实际的表的名称
- */
- public static int saveObj(JdbcTemplate jt,String tableName,Object obj){
- int re = 0;
- try{
- String sql = " insert into " + tableName + " (";
- Map<String,String> map = ObjectUtil.getProperty(obj);
- Set<String> set = map.keySet();
- for(String key : set){
- sql += (key + ",");
- }
- sql += " tableName ) ";
- sql += " values ( ";
- for(String key : set){
- sql += ("'" + map.get(key) + "',");
- }
- sql += ("'" + tableName + "' ) ");
- re = jt.update(sql);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return re;
- }
- /**
- * 根据表名称创建一张表
- * @param tableName
- */
- public static int createTable(JdbcTemplate jt,String tableName,Object obj){
- StringBuffer sb = new StringBuffer("");
- sb.append("CREATE TABLE `" + tableName + "` (");
- sb.append(" `id` int(11) NOT NULL AUTO_INCREMENT,");
- Map<String,String> map = ObjectUtil.getProperty(obj);
- Set<String> set = map.keySet();
- for(String key : set){
- sb.append("`" + key + "` varchar(255) DEFAULT '',");
- }
- sb.append(" `tableName` varchar(255) DEFAULT '',");
- sb.append(" PRIMARY KEY (`id`)");
- sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
- try {
- jt.update(sb.toString());
- return 1;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return 0;
- }
- /**
- * 查询数据库是否有某表
- * @param cnn
- * @param tableName
- * @return
- * @throws Exception
- */
- @SuppressWarnings("unchecked")
- public static boolean getAllTableName(JdbcTemplate jt,String tableName) throws Exception {
- Connection conn = jt.getDataSource().getConnection();
- ResultSet tabs = null;
- try {
- DatabaseMetaData dbMetaData = conn.getMetaData();
- String[] types = { "TABLE" };
- tabs = dbMetaData.getTables(null, null, tableName, types);
- if (tabs.next()) {
- return true;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }finally{
- tabs.close();
- conn.close();
- }
- return false;
- }
- }
动态检查是否有某表和动态创建表之前博客有提到,最主要的就是根据对象属性Map进行动态SQL拼装
但是这里这个方法有很多的限制,比如创建字段的长度,新增时字段就必须有值,因为动态SQL会进行全量字段插入
另外,新增的字段表的名称是为了之后删除和查询详细做准备的
- JdbcTemplate 动态创建表并添加数据
- 使用 JdbcTemplate 动态创建表并添加数据
- 使用 JdbcTemplate 动态创建表并添加数据
- 使用 JdbcTemplate 动态创建表并添加数据
- 使用 JdbcTemplate 动态创建表并添加数据 动态连表查询
- 动态创建表并添加数据最后用reporting显示
- 动态创建表并添加数据最后用reporting显示
- Java创建表并添加数据
- SQLite创建表并添加数据
- SQL语句创建表并添加数据
- mysql 动态创建表、添加数据
- 创建数据库并添加数据
- JS动态添加表行,并验证数据,获取数据。
- C# 动态创建DataTable表,并添加新行
- C# 动态创建DataTable表,并添加新行
- 动态创建物体并添加刚体属性
- 动态创建CMFCToolbar并添加按钮
- MFC动态创建可停靠窗口,窗口添加控件并读写控件中的数据
- 双向循环链表
- BZOJ4702 装箱游戏
- 统计学习方法读书笔记
- HDOJ 1042 N!
- JS和JAVA使用JSON方法解析
- JdbcTemplate 动态创建表并添加数据
- HTTP基础
- Eclipse启动loading descriptor for xx项目启动报错解决
- Asterisk manager API(AMI)文档(中文版)
- 提高Java学习效率的10个小计划
- MySQL优化-转
- JSP文件的构成(二)
- OC中,成员变量和属性区别
- 第一个html代码