看到Hibernate你给一个对象,他就能动态的创建配置文件里面指定的表名,然后把数据录入到数据库,当初感觉是很神奇,不过,好像Hibernate不能动态的分表创建表和录入数据
我这里写了一个公用的类,你给一个对象,告诉我按年还是按月生成表,并告诉我那个字段是不需要在表中创建的,该类就可以动态的分表创建需要的表,并录入数据
注意:
由于业务需要,这里对于字段的支持只有int和Integer,double和Double
还有String,同时对于String统一创建为了Varchar(100)的字段
表会统一创建一个id自增主键
- package com.xd.nms.util;
- import java.lang.reflect.Field;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Map;
- import java.util.Set;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.jdbc.core.JdbcTemplate;
- /**
- * @说明 动态插入数据和创建表
- * @author 崔素强
- * @version 1.0
- * @since
- */
- public class CommonTableInsert {
- public static Log logger = LogFactory.getLog(CommonTableInsert.class);
- /**
- * 入口方法
- * @param tableName 表前缀
- * @param dateFormat 格式化方法
- * @param obj 保存的对象
- * @return
- */
- @SuppressWarnings("unchecked")
- public static int insertObject(String tableName,String dateFormat,Object obj, Map noCol){
- int re = 0;
- try {
- JdbcTemplate jt = (JdbcTemplate) SpringFactory.getObject("jdbcTemplate");
- SimpleDateFormat format = new SimpleDateFormat(dateFormat);
- String tname = tableName + "_" + format.format(new Date());
- if(CommonDBUtil.getAllTableName(jt,tname)){ // 如果有某表
- re = saveObj(jt,tname,obj, noCol); // 保存数据
- }else{
- re = createTable(jt,tname,obj, noCol); // 动态创建表
- if(re == 1){
- re = saveObj(jt,tname,obj, noCol); // 保存数据
- }
- }
- } catch (Exception e) {
- logger.error("公用方法插入数据入口方法错误", e);
- }
- return re;
- }
- /**
- * 保存方法,注意这里传递的是实际的表的名称
- */
- @SuppressWarnings("unchecked")
- private static int saveObj(JdbcTemplate jt,String tableName,Object obj, Map noCol){
- int re = 0;
- StringBuffer sb = new StringBuffer("");
- try{
- sb.append(" insert into " + tableName + " (");
- Map<String,String> map = ObjectUtil.getProAndValMap(obj); // 对象的属性和属性值
- Map<String,String> mapType = ObjectUtil.getProTypeMap(obj); // 对象的属性类型列表
- Set<String> set = map.keySet();
- for(String key : set){
- // 如果该列不是 非处理列
- if(noCol.get(key) == null){
- sb.append(key + ",");
- }
- }
- sb.append(" tableName ) ");
- sb.append(" values ( ");
- for(String key : set){
- if(noCol.get(key) == null){
- if(mapType.get(key).equals("class java.lang.String")){
- sb.append("'" + (map.get(key) + "',"));
- }else{
- sb.append(map.get(key) + ",");
- }
- }
- }
- sb.append("'" + tableName + "'); ");
- re = jt.update(sb.toString());
- } catch (Exception e) {
- logger.error("公用方法录入数据时错误", e);
- logger.error("公用方法录入数据语句:" + sb.toString());
- }
- return re;
- }
- /**
- * 根据表名称 和 实体属性 创建一张表
- * @param tableName
- * @param obj 具体生成什么样的表看该对象
- */
- @SuppressWarnings("unchecked")
- private static int createTable(JdbcTemplate jt,String tableName,Object obj, Map noCol){
- StringBuffer sb = new StringBuffer("");
- sb.append("CREATE TABLE `" + tableName + "` (");
- sb.append(" `id` int(11) NOT NULL AUTO_INCREMENT,");
- Class c = obj.getClass();
- Field field[] = c.getDeclaredFields();
- for (Field f : field) {
- if(noCol.get(f.getName()) == null){
- String type = f.getType().toString();
- if(type.equals("class java.lang.String")){// Str
- sb.append("`" + f.getName() + "` varchar(100) DEFAULT NULL,");
- }else if(type.equals("int") || type.equals("class java.lang.Integer")){// int
- sb.append("`" + f.getName() + "` int(11) DEFAULT NULL,");
- }else if(type.equals("double") || type.equals("class java.lang.Double")){// double
- sb.append("`" + f.getName() + "` double DEFAULT NULL,");
- }
- }
- }
- sb.append(" `tableName` varchar(255) DEFAULT NULL,");
- sb.append(" PRIMARY KEY (`id`)");
- sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
- try {
- jt.update(sb.toString());
- return 1;
- } catch (Exception e) {
- logger.error("公用方法生成表时错误", e);
- logger.error("公用方法生成表语句:" + sb.toString());
- }
- return 0;
- }
- }
这个对于之前写的那个动态建表,新增了过滤不需要在表中创建的字段
原理就是读取对象的各个字段属性,如果能加以配置文件或者读取对象属性的标记,那其实能做到基本和Hibernate一致,不但能支持多种类型,还能做字段校验等