存在即合理,重复轮子orm java版本

1,业务描述前序?

需求来源于,公司的运营部门。本人所在公司(私营,游戏行业公司),从初创业,我就进入公司,一直致力于服务器核心研发。

公司成立块3年了,前后出产了4款游戏,一直在重复的制造公司游戏对应的游戏后台管理工具(web版本);

今年年初公司成立里运营部门,不仅开始运营公司自己产品也代理了其他公司产品。越来越觉得做出统一的平台管理和游戏后台管理工具迫切需求;

既然有需求,就有市场,就需要研发;

2,重复造轮子

既然是统一的管理平台,问题来了,可能做过游戏或者游戏后台相关的人员都知道,管理平台,其实需求简单明了,业务简单清晰!

问题是在于数据量很大,针对一个游戏,一个玩家,一分钟就可能产出上百条日志记录(升级,获得任何奖励,消耗任何道具等等);

然而在面对一个游戏,多个服务器,多个游戏,很多个服务器情况下,日志量很难预估;且还有一个特色,那就是一般情况下一个月以前的日志其实是完全无用,并且可以删除的;

3,DBA的重要性

我们公司到目前为止没有专业的DBA和DBC,数据库相关的设计和操作只能自己来;

(我的40米大刀呢?)

没办法只能自己上

宝宝心里苦啊

好了废话不多说,

由此上面的综合原因,我们考虑了,日志,不同的业务逻辑日志不同的实体模型(数据库表结构),

但是每一天划分开来(比如Test 表今天的Test_2016_11_04,明天:Test_2016_11_05);

这样的业务逻辑下我没有发现比较适合自己的orm框架,或者说我英文不好,看不懂一些api吧,

于是就有了重复造轮子的事情;

3,我的业务量在哪里?

我的业务量主要还是在写入数据,作为日志服务器(http api 提供方式)只提供数据接收,验证,存取操作;

也就说我只需要考虑大并发情况下,批量写入问题,并且防止好sql注入式攻击就好;

4,代码实现

   1 package net.sz.engine.db;
   2 
   3 import java.io.ByteArrayInputStream;
   4 import java.io.ByteArrayOutputStream;
   5 import java.io.IOException;
   6 import java.io.ObjectInputStream;
   7 import java.io.ObjectOutputStream;
   8 import java.lang.reflect.Field;
   9 import java.lang.reflect.InvocationTargetException;
  10 import java.lang.reflect.Method;
  11 import java.lang.reflect.Modifier;
  12 import java.sql.Connection;
  13 import java.sql.Date;
  14 import java.sql.PreparedStatement;
  15 import java.sql.ResultSet;
  16 import java.sql.SQLException;
  17 import java.util.ArrayList;
  18 import java.util.HashMap;
  19 import java.util.List;
  20 import java.util.Map;
  21 import java.util.concurrent.ConcurrentHashMap;
  22 import javax.persistence.Column;
  23 import javax.persistence.GeneratedValue;
  24 import javax.persistence.Id;
  25 import javax.persistence.Table;
  26 import net.sz.engine.utils.StringUtil;
  27 import org.apache.log4j.Logger;
  28 
  29 /**
  30  *
  31  * <br>
  32  * author 失足程序员<br>
  33  * mail 492794628@qq.com<br>
  34  * phone 13882122019<br>
  35  */
  36 public abstract class Dao {
  37 
  38     private static final Logger log = Logger.getLogger(Dao.class);
  39     /**
  40      * 数据库连接
  41      */
  42     protected String dbUrl;
  43     /**
  44      * 数据库名字
  45      */
  46     protected String dbName;
  47     /**
  48      * 数据库用户
  49      */
  50     protected String dbUser;
  51     /**
  52      * 数据库密码
  53      */
  54     protected String dbPwd;
  55     /**
  56      * 是否显示sql语句
  57      */
  58     protected boolean showSql;
  59     /**
  60      * 存储所有类型解析
  61      */
  62     protected static final ConcurrentHashMap<String, List<SqlColumn>> sqlColumnMap = new ConcurrentHashMap<>();
  63 
  64     public Dao() {
  65     }
  66 
  67     //<editor-fold defaultstate="collapsed" desc="构造函数 public Dao(String dbUrl, String dbName, String dbUser, String dbPwd, boolean showSql)">
  68     /**
  69      * 构造函数
  70      *
  71      * @param dbUrl
  72      * @param dbName
  73      * @param dbUser
  74      * @param dbPwd
  75      * @param showSql
  76      */
  77     public Dao(String dbUrl, String dbName, String dbUser, String dbPwd, boolean showSql) {
  78         this.dbUrl = dbUrl;
  79         this.dbName = dbName;
  80         this.dbUser = dbUser;
  81         this.dbPwd = dbPwd;
  82         this.showSql = showSql;
  83     }
  84     //</editor-fold>
  85 
  86     //<editor-fold defaultstate="collapsed" desc="获取表名 protected String getTableName(Object o)">
  87     /**
  88      * 获取表名
  89      *
  90      * @param oClass
  91      * @return
  92      */
  93     protected String getTableName(Class<?> oClass) {
  94         //判断指定类型的注释是否存在于此元素上
  95         boolean isHaveTable = oClass.isAnnotationPresent(Table.class);
  96         if (!isHaveTable) {
  97             return oClass.getSimpleName();//不存在就不需要获取其表名
  98         }
  99         Table table = oClass.getAnnotation(Table.class);//拿到对应的表格注解类型
 100         return table.name();//返回注解中的值,也就是表名
 101     }
 102     //</editor-fold>
 103 
 104     //<editor-fold defaultstate="collapsed" desc="设置字段值,插入数据库,支持sql注入攻击  protected void setStmtParams(PreparedStatement stmt, SqlColumn sqlColumn, Integer nums, Object value)">
 105     /**
 106      * 设置字段值,插入数据库,支持sql注入攻击
 107      *
 108      * @param stmt
 109      * @param sqlColumn
 110      * @param nums
 111      * @param value
 112      * @throws SQLException
 113      * @throws IOException
 114      */
 115     protected void setStmtParams(PreparedStatement stmt, SqlColumn sqlColumn, Integer nums, Object value) throws SQLException, IOException {
 116         switch (sqlColumn.getClassType().getName().toLowerCase()) {
 117             case "int":
 118             case "java.lang.integer":
 119                 if (value == null) {
 120                     if (!sqlColumn.isColumnNullAble()) {
 121                         value = 0;
 122                     }
 123                 }
 124                 if (value == null) {
 125                     stmt.setObject(nums, null);
 126                 } else {
 127                     stmt.setInt(nums, (Integer) value);
 128                 }
 129 
 130                 break;
 131             case "string":
 132             case "java.lang.string":
 133                 if (value == null) {
 134                     if (!sqlColumn.isColumnNullAble()) {
 135                         value = "";
 136                     }
 137                 }
 138                 stmt.setString(nums, (String) value);
 139                 break;
 140             case "double":
 141             case "java.lang.double":
 142                 if (value == null) {
 143                     if (!sqlColumn.isColumnNullAble()) {
 144                         value = 0.0;
 145                     }
 146                 }
 147                 if (value == null) {
 148                     stmt.setObject(nums, null);
 149                 } else {
 150                     stmt.setDouble(nums, (Double) value);
 151                 }
 152                 break;
 153             case "float":
 154             case "java.lang.float":
 155                 if (value == null) {
 156                     if (!sqlColumn.isColumnNullAble()) {
 157                         value = 0.0;
 158                     }
 159                 }
 160                 if (value == null) {
 161                     stmt.setObject(nums, null);
 162                 } else {
 163                     stmt.setFloat(nums, (float) value);
 164                 }
 165                 break;
 166             case "long":
 167             case "java.lang.long":
 168                 if (value == null) {
 169                     if (!sqlColumn.isColumnNullAble()) {
 170                         value = 0.0;
 171                     }
 172                 }
 173                 if (value == null) {
 174                     stmt.setObject(nums, null);
 175                 } else {
 176                     stmt.setLong(nums, (long) value);
 177                 }
 178                 break;
 179             case "byte":
 180             case "java.lang.byte":
 181                 if (value == null) {
 182                     if (!sqlColumn.isColumnNullAble()) {
 183                         value = 0.0;
 184                     }
 185                 }
 186                 if (value == null) {
 187                     stmt.setObject(nums, null);
 188                 } else {
 189                     stmt.setByte(nums, (byte) value);
 190                 }
 191                 break;
 192             case "short":
 193             case "java.lang.short":
 194                 if (value == null) {
 195                     if (!sqlColumn.isColumnNullAble()) {
 196                         value = 0.0;
 197                     }
 198                 }
 199                 if (value == null) {
 200                     stmt.setObject(nums, null);
 201                 } else {
 202                     stmt.setShort(nums, (short) value);
 203                 }
 204                 break;
 205             case "date":
 206             case "java.lang.date":
 207                 if (value == null) {
 208                     if (!sqlColumn.isColumnNullAble()) {
 209                         value = 0.0;
 210                     }
 211                 }
 212                 stmt.setDate(nums, (Date) value);
 213                 break;
 214             default: {
 215                 if (value == null) {
 216                     stmt.setObject(nums, null);
 217                 } else {
 218                     stmt.setBytes(nums, writeObject(value));
 219                 }
 220             }
 221         }
 222     }
 223     //</editor-fold>
 224 
 225     //<editor-fold defaultstate="collapsed" desc="设置字段值,插入数据库,支持sql注入攻击  protected void setStmtParams(PreparedStatement stmt, SqlColumn sqlColumn, Integer nums, Object value)">
 226     /**
 227      * 设置字段值,插入数据库,支持sql注入攻击
 228      *
 229      * @param stmt
 230      * @param sqlColumn
 231      * @param nums
 232      * @param value
 233      * @throws SQLException
 234      * @throws IOException
 235      */
 236     protected void setStmtParams(PreparedStatement stmt, Integer nums, Object value) throws SQLException, IOException {
 237         if (value == null) {
 238             stmt.setObject(nums, null);
 239             return;
 240         }
 241         switch (value.getClass().getName().toLowerCase()) {
 242             case "int":
 243             case "java.lang.integer":
 244                 stmt.setInt(nums, (Integer) value);
 245                 break;
 246             case "string":
 247             case "java.lang.string":
 248                 stmt.setString(nums, (String) value);
 249                 break;
 250             case "double":
 251             case "java.lang.double":
 252                 stmt.setDouble(nums, (Double) value);
 253                 break;
 254             case "float":
 255             case "java.lang.float":
 256                 stmt.setFloat(nums, (float) value);
 257                 break;
 258             case "long":
 259             case "java.lang.long":
 260                 stmt.setLong(nums, (long) value);
 261                 break;
 262             case "byte":
 263             case "java.lang.byte":
 264                 stmt.setByte(nums, (byte) value);
 265                 break;
 266             case "short":
 267             case "java.lang.short":
 268                 stmt.setShort(nums, (short) value);
 269                 break;
 270             case "date":
 271             case "java.lang.date":
 272                 stmt.setDate(nums, (Date) value);
 273                 break;
 274             default: {
 275                 stmt.setBytes(nums, writeObject(value));
 276             }
 277         }
 278     }
 279     //</editor-fold>
 280 
 281     //<editor-fold defaultstate="collapsed" desc="反射获取字段信息 过滤 transient 字段 protected Map<String, SqlColumn> getColumns(Object o)">
 282     /**
 283      * 反射获取字段信息 过滤 transient 字段
 284      *
 285      * @param clazz
 286      * @return
 287      */
 288     protected List<SqlColumn> getColumns(Class<?> clazz) {
 289         List<SqlColumn> cols = sqlColumnMap.get(clazz.getName());
 290         if (cols != null) {
 291             return cols;
 292         }
 293         //获取对象中所有的属性
 294         Field[] fields = clazz.getDeclaredFields();
 295         Method[] methods = clazz.getMethods();
 296         cols = new ArrayList<>();
 297         boolean ispakey = false;
 298         //遍历所有属性
 299         for (Field field : fields) {
 300             //忽略字段,静态字段,最终字段,不会书写到数据库
 301             if (Modifier.isTransient(field.getModifiers())
 302                     || Modifier.isStatic(field.getModifiers())
 303                     || Modifier.isFinal(field.getModifiers())) {
 304                 if (showSql) {
 305                     log.error("类:" + clazz.getName() + " 字段:" + field.getName() + " is transient or static or final;");
 306                 }
 307                 continue;
 308             }
 309 
 310             //如果属性上有对应的列注解类型则获取这个注解类型
 311             Column column = field.getAnnotation(Column.class);
 312             SqlColumn sqlColumn = new SqlColumn();
 313             sqlColumn.setColumnName(field.getName());
 314             sqlColumn.setFieldName(field.getName());
 315 
 316             if (column != null) {
 317                 if (column.name() != null && !column.name().trim().isEmpty()) {
 318                     sqlColumn.setColumnName(column.name().trim());
 319                 }
 320 
 321                 if (column.length() > 0) {
 322                     sqlColumn.setColunmLength(column.length());
 323                 }
 324 
 325                 sqlColumn.setColumnNullAble(column.nullable());
 326 
 327                 if (column.columnDefinition() != null) {
 328                     sqlColumn.setColumnDefinition(column.columnDefinition());
 329                 }
 330             }
 331             //拿到对应属性的类型,然后根据对应的类型去声明字段类型
 332             Class<?> type = field.getType();
 333 
 334             sqlColumn.setClassType(type);
 335 
 336             String columnvalue = null;
 337             switch (type.getName().toLowerCase()) {
 338                 case "int":
 339                 case "java.lang.integer":
 340                     columnvalue = "int(4)";
 341                     break;
 342                 case "string":
 343                 case "java.lang.string":
 344                     if (sqlColumn.getColunmLength() < 1000) {
 345                         columnvalue = "varchar(" + sqlColumn.getColunmLength() + ")";
 346                     } else {
 347                         columnvalue = "text(" + sqlColumn.getColunmLength() + ")";
 348                     }
 349                     break;
 350                 case "double":
 351                 case "java.lang.double":
 352                     columnvalue = "double";
 353                     break;
 354                 case "float":
 355                 case "java.lang.float":
 356                     columnvalue = "float";
 357                     break;
 358                 case "byte":
 359                 case "java.lang.byte":
 360                     columnvalue = "tinyint(1)";
 361                     break;
 362                 case "long":
 363                 case "java.lang.long":
 364                     columnvalue = "bigint";
 365                     break;
 366                 case "short":
 367                 case "java.lang.short":
 368                     columnvalue = "tinyint(2)";
 369                     break;
 370                 default:
 371 
 372                     columnvalue = "blob";
 373 
 374                     break;
 375             }
 376             if (columnvalue != null) {
 377                 //如果属性上有对应的主键ID注解类型则获取这个注解类型
 378                 Id tpid = field.getAnnotation(Id.class);
 379                 if (tpid != null) {
 380                     ispakey = true;
 381                     sqlColumn.setColumnkey(true);
 382                     sqlColumn.setColumnNullAble(false);
 383                     GeneratedValue annotation = field.getAnnotation(GeneratedValue.class);
 384                     //判断主键是否为自动增长
 385                     if (annotation != null) {
 386                         sqlColumn.setColumnAuto(true);
 387                     }
 388                 }
 389 
 390                 if (sqlColumn.isColumnNullAble()) {
 391                     columnvalue += " null";
 392                 } else {
 393                     columnvalue += " not null";
 394                 }
 395 
 396                 if (sqlColumn.isColumnkey()) {
 397                     if (sqlColumn.isColumnAuto()) {
 398                         columnvalue += " auto_increment";
 399                     }
 400                     columnvalue += " primary key";
 401                 }
 402 
 403                 sqlColumn.setValue(columnvalue);
 404 
 405                 for (Method method : methods) {
 406                     String methodName = method.getName().toLowerCase();//获取每一个方法名
 407                     if (methodName.equals("get" + sqlColumn.getFieldName().toLowerCase())) {
 408                         sqlColumn.setGetMethod(method);
 409                         break;
 410                     }
 411                 }
 412 
 413                 for (Method method : methods) {
 414                     String methodName = method.getName().toLowerCase();//获取每一个方法名
 415                     if (methodName.equals("set" + sqlColumn.getFieldName().toLowerCase())) {
 416                         sqlColumn.setSetMethod(method);
 417                         break;
 418                     }
 419                 }
 420 
 421                 cols.add(sqlColumn);
 422             } else {
 423                 if (showSql) {
 424                     log.error("类:" + clazz.getName() + " 无法识别的字段:" + field.getName() + " ;");
 425                 }
 426             }
 427         }
 428         if (!ispakey) {
 429             throw new UnsupportedOperationException("实体类不允许没有组件字段:" + clazz.getName());
 430         }
 431         if (cols.isEmpty()) {
 432             throw new UnsupportedOperationException("实体模型未有任何字段:" + clazz.getName());
 433         }
 434         sqlColumnMap.put(clazz.getName(), cols);
 435         return cols;
 436     }
 437     //</editor-fold>
 438 
 439     //<editor-fold defaultstate="collapsed" desc="序列化一个对象 protected byte[] writeObject(Object obj) ">
 440     /**
 441      * 序列化一个对象
 442      *
 443      * @param obj 要序列化的对象
 444      * @return byte数组
 445      * @throws java.io.IOException
 446      */
 447     protected byte[] writeObject(Object obj) throws IOException {
 448         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 449         ObjectOutputStream out = null;
 450         try {
 451             out = new ObjectOutputStream(baos);
 452             out.writeObject(obj);
 453         } finally {
 454             try {
 455                 out.close();
 456             } catch (IOException e) {
 457             }
 458         }
 459         return baos.toByteArray();
 460     }
 461     //</editor-fold>
 462 
 463     //<editor-fold defaultstate="collapsed" desc="序列化一个对象 protected byte[] writeObject(Object obj) ">
 464     /**
 465      * 序列化一个对象
 466      *
 467      * @param bytes
 468      * @return byte数组
 469      * @throws java.io.IOException
 470      * @throws java.lang.ClassNotFoundException
 471      */
 472     protected Object readObject(byte[] bytes) throws IOException, ClassNotFoundException {
 473         try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) {
 474             try (ObjectInputStream ois = new ObjectInputStream(bis)) {
 475                 return ois.readObject();
 476             }
 477         }
 478     }
 479     //</editor-fold>
 480 
 481     //<editor-fold defaultstate="collapsed" desc="创建表 public void createTable(List<Object> objs)">
 482     /**
 483      * 创建表
 484      *
 485      * @param objs 所有需要创建表的实体对象
 486      * @throws java.sql.SQLException
 487      * @throws java.io.IOException
 488      * @throws java.lang.ClassNotFoundException
 489      */
 490     public void createTable(List<Object> objs) throws SQLException, IOException, ClassNotFoundException {
 491         //遍历所有要创建表的对象
 492         for (Object obj : objs) {
 493             createTable(obj);
 494         }
 495     }
 496     //</editor-fold>
 497 
 498     //<editor-fold defaultstate="collapsed" desc="创建表 public void createTable(Object obj)">
 499     /**
 500      * 创建表
 501      *
 502      * @param obj
 503      * @throws SQLException
 504      * @throws IOException
 505      * @throws ClassNotFoundException
 506      */
 507     public void createTable(Object obj) throws SQLException, IOException, ClassNotFoundException {
 508         Class<?> aClass = obj.getClass();
 509         String talbeName = getTableName(obj.getClass());
 510         //拿到表的所有要创建的字段名
 511         List<SqlColumn> columns = getColumns(aClass);
 512         createTable(obj, talbeName, columns);
 513     }
 514     //</editor-fold>
 515 
 516     //<editor-fold defaultstate="collapsed" desc="创建表 protected abstract void createTable(Object o, String tableName, List<SqlColumn> columns)">
 517     /**
 518      * 创建表
 519      *
 520      * @param o
 521      * @param tableName
 522      * @param columns
 523      * @throws java.sql.SQLException
 524      * @throws java.lang.ClassNotFoundException
 525      * @throws java.io.IOException
 526      */
 527     protected abstract void createTable(Object o, String tableName, List<SqlColumn> columns) throws SQLException, ClassNotFoundException, IOException;
 528     //</editor-fold>
 529 
 530     //<editor-fold defaultstate="collapsed" desc="检查表是否存在 public abstract boolean existsTable(String tableName)">
 531     /**
 532      * 检查表是否存在
 533      *
 534      * @param tableName
 535      * @return
 536      * @throws java.sql.SQLException
 537      * @throws java.lang.ClassNotFoundException
 538      * @throws java.io.IOException
 539      */
 540     public abstract boolean existsTable(String tableName) throws SQLException, ClassNotFoundException, IOException;
 541     //</editor-fold>
 542 
 543     //<editor-fold defaultstate="collapsed" desc="获取数据库的连接 protected abstract Connection getConnection()">
 544     /**
 545      * 获取数据库的连接
 546      *
 547      * @return
 548      * @throws java.sql.SQLException
 549      * @throws java.lang.ClassNotFoundException
 550      */
 551     protected abstract Connection getConnection() throws SQLException, ClassNotFoundException, ClassNotFoundException;
 552     //</editor-fold>
 553 
 554     //<editor-fold defaultstate="collapsed" desc="插入对象 public boolean addInsertSql(List<Object> os)">
 555     /**
 556      * 插入对象
 557      *
 558      * @param os
 559      * @return
 560      * @throws IOException
 561      * @throws ClassNotFoundException
 562      * @throws SQLException
 563      * @throws IllegalAccessException
 564      * @throws IllegalArgumentException
 565      * @throws InvocationTargetException
 566      */
 567     public boolean addInsertSql(List<Object> os) throws IOException, ClassNotFoundException, SQLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 568         if (os == null || os.isEmpty()) {
 569             return false;
 570         }
 571         Object[] toArray = os.toArray(new Object[0]);
 572         return addInsertSql(toArray);
 573     }
 574     //</editor-fold>
 575 
 576     //<editor-fold defaultstate="collapsed" desc="插入对象到数据库 public boolean addInsertSql(Object... os)">
 577     /**
 578      * 插入对象到数据库
 579      *
 580      * @param os os 必须是对同一个对象
 581      * @return
 582      * @throws IOException
 583      * @throws ClassNotFoundException
 584      * @throws SQLException
 585      * @throws IllegalAccessException
 586      * @throws IllegalArgumentException
 587      * @throws InvocationTargetException
 588      */
 589     public boolean addInsertSql(Object... os) throws IOException, ClassNotFoundException, SQLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 590         if (os == null || os.length == 0) {
 591             return false;
 592         }
 593 
 594         Object objfirst = os[0];
 595         //得到对象的类
 596         Class<?> clazz = objfirst.getClass();
 597         //获取表名
 598         String tableName = getTableName(clazz);
 599         //拿到表的所有要创建的字段名
 600         List<SqlColumn> columns = getColumns(clazz);
 601         //这里如果不存在字段名就不需要创建了
 602         if (columns == null || columns.isEmpty()) {
 603             throw new UnsupportedOperationException("实体类没有任何字段,");
 604         }
 605 
 606         if (!existsTable(tableName)) {
 607             createTable(objfirst, tableName, columns);
 608         }
 609 
 610         StringBuilder builder = new StringBuilder();
 611 
 612         builder.append("insert into `").append(tableName).append("` (");
 613         //将所有的字段拼接成对应的SQL语句
 614         for (SqlColumn value : columns) {
 615             builder.append("`").append(value.getColumnName()).append("`, ");
 616         }
 617         builder.delete(builder.length() - 2, builder.length());
 618         builder.append(") values ");
 619 
 620         for (int i = 0; i < os.length; i++) {
 621             builder.append("\n(");
 622             for (int j = 0; j < columns.size(); j++) {
 623                 builder.append("?");
 624                 if (j < columns.size() - 1) {
 625                     builder.append(",");
 626                 }
 627                 builder.append(" ");
 628             }
 629             builder.append(")");
 630             if (i < os.length - 1) {
 631                 builder.append(",");
 632             }
 633         }
 634         builder.append(";");
 635         String sqlString = builder.toString();
 636         Connection con = getConnection();
 637         try (PreparedStatement prepareCall = con.prepareStatement(sqlString)) {
 638             for (int i = 0; i < os.length; i++) {
 639                 int tmp = i * columns.size();
 640                 int j = 1;
 641                 Object obj = os[i];
 642                 for (SqlColumn value : columns) {
 643                     Object invoke = value.getGetMethod().invoke(obj);
 644                     setStmtParams(prepareCall, value, tmp + j, invoke);
 645                     j++;
 646                 }
 647             }
 648 
 649             int execute = prepareCall.executeUpdate();
 650 
 651             if (showSql) {
 652                 log.error("执行 " + prepareCall.toString() + " 添加数据 表:" + tableName + " 结果 影响行数:" + execute);
 653             }
 654 
 655             if (execute <= 0) {
 656                 return false;
 657             }
 658 
 659         }
 660         return true;
 661     }
 662     //</editor-fold>
 663 
 664     //<editor-fold defaultstate="collapsed" desc="返回结果集 public <T> List<T> getList(Class<T> clazz, String whereSqlString, Object... strs)">
 665     /**
 666      * 返回结果集
 667      *
 668      * @param <T>
 669      * @param clazz
 670      * @param whereSqlString 例如: a=? and b=? 或者 a=? or a=? 这样才能防止sql注入攻击
 671      * @param strs
 672      * @return
 673      * @throws SQLException
 674      * @throws ClassNotFoundException
 675      * @throws IOException
 676      * @throws InstantiationException
 677      * @throws IllegalAccessException
 678      * @throws IllegalArgumentException
 679      * @throws InvocationTargetException
 680      */
 681     public <T> List<T> getList(Class<T> clazz, String whereSqlString, Object... strs) throws SQLException, ClassNotFoundException, IOException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 682         List<T> ts = new ArrayList<>();
 683         //获取表名
 684         String tableName = getTableName(clazz);
 685         //拿到表的所有要创建的字段名
 686         List<SqlColumn> columns = getColumns(clazz);
 687 
 688         List<Map<String, Object>> rs = getResultSet(tableName, columns, whereSqlString, strs);
 689         //得到对象的所有的方法
 690         for (Map<String, Object> r : rs) {
 691             T object = getObject(r, clazz, columns);
 692             ts.add(object);
 693         }
 694         return ts;
 695     }
 696     //</editor-fold>
 697 
 698     //<editor-fold defaultstate="collapsed" desc="返回查询结果集 public ResultSet getResultSet(Class<?> clazz, String whereSqlString, Object... strs)">
 699     /**
 700      * 返回查询结果集
 701      *
 702      * @param clazz
 703      * @param whereSqlString 例如: a=? and b=? 或者 a=? or a=? 这样才能防止sql注入攻击
 704      * @param strs
 705      * @return
 706      * @throws SQLException
 707      * @throws ClassNotFoundException
 708      * @throws IOException
 709      * @throws InstantiationException
 710      * @throws IllegalAccessException
 711      * @throws IllegalArgumentException
 712      * @throws InvocationTargetException
 713      */
 714     public List<Map<String, Object>> getResultSet(Class<?> clazz, String whereSqlString, Object... strs) throws SQLException, ClassNotFoundException, IOException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 715 
 716         if (clazz == null) {
 717             throw new UnsupportedOperationException("obj or clzz 为 null,");
 718         }
 719 
 720         //获取表名
 721         String tableName = getTableName(clazz);
 722         //拿到表的所有要创建的字段名
 723         List<SqlColumn> columns = getColumns(clazz);
 724 
 725         List<Map<String, Object>> resultSet = getResultSet(tableName, columns, whereSqlString, strs);
 726 
 727         return resultSet;
 728     }
 729     //</editor-fold>
 730 
 731     //<editor-fold defaultstate="collapsed" desc="返回查询结果集 public abstract <T> List<T> getList(Object obj, String... strs)">
 732     /**
 733      * 返回查询结果集
 734      *
 735      * @param tableName
 736      * @param columns
 737      * @param whereSqlString 范例 a=? and b=? 或者 a=? or a=?
 738      * @param strs
 739      * @return
 740      * @throws SQLException
 741      * @throws IOException
 742      * @throws java.lang.InstantiationException
 743      * @throws java.lang.IllegalAccessException
 744      * @throws java.lang.reflect.InvocationTargetException
 745      * @throws java.lang.ClassNotFoundException
 746      */
 747     protected List<Map<String, Object>> getResultSet(String tableName, List<SqlColumn> columns, String whereSqlString, Object... strs) throws SQLException, ClassNotFoundException, IOException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
 748         //这里如果不存在字段名就不需要创建了
 749         if (columns == null || columns.isEmpty()) {
 750             throw new UnsupportedOperationException("实体类没有任何字段,");
 751         }
 752         StringBuilder builder = new StringBuilder();
 753         builder.append("SELECT ");
 754         int i = 0;
 755         for (SqlColumn value : columns) {
 756             builder.append("`").append(value.getColumnName()).append("`");
 757             if (i < columns.size() - 1) {
 758                 builder.append(",");
 759             }
 760             i++;
 761         }
 762         builder.append(" FROM `").append(tableName).append("` ");
 763         if (whereSqlString != null && whereSqlString.length() > 0) {
 764             builder.append(" WHERE ").append(whereSqlString);
 765         }
 766         String sqlString = builder.toString();
 767         ResultSet rs = null;
 768         List<Map<String, Object>> res = new ArrayList<>();
 769         Connection con = getConnection();
 770         try (PreparedStatement prepareStatement = con.prepareStatement(sqlString)) {
 771             if (strs != null && strs.length > 0) {
 772                 for (int j = 0; j < strs.length; j++) {
 773                     setStmtParams(prepareStatement, j + 1, strs[j]);
 774                 }
 775             }
 776             if (showSql) {
 777                 log.error("\n" + prepareStatement.toString());
 778             }
 779             rs = prepareStatement.executeQuery();
 780 
 781             while (rs.next()) {
 782                 Map<String, Object> map = new HashMap<>();
 783                 int columnCount = rs.getMetaData().getColumnCount();
 784                 for (int j = 1; j < columnCount + 1; j++) {
 785                     Object object = rs.getObject(j);
 786                     String columnName = rs.getMetaData().getColumnName(j);
 787                     map.put(columnName, object);
 788                 }
 789                 res.add(map);
 790             }
 791         }
 792         return res;
 793     }
 794     //</editor-fold>
 795 
 796     //<editor-fold defaultstate="collapsed" desc="返回结果对象 protected <T> T getObject(ResultSet rs, Class<T> clazz, List<SqlColumn> columns)">
 797     /**
 798      * 返回结果对象
 799      *
 800      * @param <T>
 801      * @param rs
 802      * @param clazz
 803      * @param columns
 804      * @return
 805      * @throws InstantiationException
 806      * @throws IllegalAccessException
 807      * @throws SQLException
 808      * @throws IllegalArgumentException
 809      * @throws InvocationTargetException
 810      * @throws IOException
 811      * @throws ClassNotFoundException
 812      */
 813     protected <T> T getObject(Map<String, Object> rs, Class<T> clazz, List<SqlColumn> columns) throws InstantiationException, IllegalAccessException, SQLException, IllegalArgumentException, InvocationTargetException, IOException, ClassNotFoundException {
 814         /* 生成一个实例 */
 815         T obj = clazz.newInstance();
 816         for (SqlColumn column : columns) {
 817             Method m = column.getSetMethod();
 818             m.invoke(obj, getObject(rs, column.getColumnName(), column.getClassType()));
 819         }
 820         return obj;
 821     }
 822     //</editor-fold>
 823 
 824     //<editor-fold defaultstate="collapsed" desc="获取一个已经返回的结果集的值 public Object getObject(ResultSet rs, String columnName, Class<?> columnType)">
 825     /**
 826      * 获取一个已经返回的结果集的值
 827      *
 828      * @param rs
 829      * @param columnName
 830      * @param columnType
 831      * @return
 832      * @throws SQLException
 833      * @throws IOException
 834      * @throws ClassNotFoundException
 835      */
 836     public Object getObject(Map<String, Object> rs, String columnName, Class<?> columnType) throws SQLException, IOException, ClassNotFoundException {
 837         Object obj = rs.get(columnName);
 838 
 839         String toLowerCase = columnType.getName().toLowerCase();
 840         switch (toLowerCase) {
 841             case "int":
 842             case "java.lang.integer":
 843                 obj = (Integer) obj;
 844                 break;
 845             case "string":
 846             case "java.lang.string":
 847                 obj = (String) obj;
 848                 break;
 849             case "double":
 850             case "java.lang.double":
 851                 obj = (Double) obj;
 852                 break;
 853             case "float":
 854             case "java.lang.float":
 855                 obj = (Float) obj;
 856                 break;
 857             case "long":
 858             case "java.lang.long":
 859                 obj = (Long) obj;
 860                 break;
 861             case "byte":
 862             case "java.lang.byte":
 863                 obj = (Byte) obj;
 864                 break;
 865             case "short":
 866             case "java.lang.short":
 867                 obj = (Short) obj;
 868                 break;
 869             case "date":
 870             case "java.lang.date":
 871                 obj = (Date) obj;
 872                 break;
 873             default: {
 874                 byte[] bytes = (byte[]) obj;
 875                 if (bytes != null) {
 876                     obj = readObject(bytes);
 877                 } else {
 878                     obj = null;
 879                 }
 880 //                byte[] bytes = rs.getBytes(columnName);
 881 //                if (bytes != null) {
 882 //                    obj = readObject(bytes);
 883 //                }
 884             }
 885         }
 886         return obj;
 887     }
 888     //</editor-fold>
 889 
 890     //<editor-fold defaultstate="collapsed" desc="更新数据 public boolean update(Object... objs)">
 891     /**
 892      * 更新数据
 893      *
 894      * @param objs
 895      * @return
 896      * @throws SQLException
 897      * @throws ClassNotFoundException
 898      * @throws IOException
 899      * @throws IllegalAccessException
 900      * @throws IllegalArgumentException
 901      * @throws InvocationTargetException
 902      */
 903     public boolean update(Object... objs) throws SQLException, ClassNotFoundException, IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 904         for (Object obj : objs) {
 905             update(obj);
 906         }
 907         return true;
 908     }
 909     //</editor-fold>
 910 
 911     //<editor-fold defaultstate="collapsed" desc="更新数据 public boolean update(Object obj)">
 912     /**
 913      * 更新数据
 914      *
 915      * @param obj
 916      * @return
 917      * @throws SQLException
 918      * @throws ClassNotFoundException
 919      * @throws IOException
 920      * @throws IllegalAccessException
 921      * @throws IllegalArgumentException
 922      * @throws InvocationTargetException
 923      */
 924     public boolean update(Object obj) throws SQLException, ClassNotFoundException, IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
 925         if (obj == null) {
 926             throw new UnsupportedOperationException("obj is null");
 927         }
 928 
 929         String tableName = getTableName(obj.getClass());
 930         List<SqlColumn> columns = getColumns(obj.getClass());
 931         StringBuilder builder = new StringBuilder();
 932         builder.append("update `").append(tableName).append("` set");
 933         /* 需要更新的字段 */
 934         List<SqlColumn> addValues = new ArrayList<>();
 935         /* 主键字段 */
 936         List<SqlColumn> keyValues = new ArrayList<>();
 937 
 938         for (SqlColumn column : columns) {
 939             if (!column.isColumnkey()) {
 940                 if (!addValues.isEmpty()) {
 941                     builder.append(",");
 942                 }
 943                 /* 不是主键 */
 944                 builder.append(" `").append(column.getColumnName()).append("` = ?");
 945                 addValues.add(column);
 946             }
 947         }
 948 
 949         for (SqlColumn column : columns) {
 950             if (column.isColumnkey()) {
 951 
 952                 if (keyValues.isEmpty()) {
 953                     builder.append(" where ");
 954                 } else {
 955                     builder.append(" and ");
 956                 }
 957 
 958                 keyValues.add(column);
 959 
 960                 /* 不是主键 */
 961                 builder.append(" `").append(column.getColumnName()).append("` = ? ");
 962             }
 963         }
 964 
 965         Connection con = getConnection();
 966         try (PreparedStatement prepareStatement = con.prepareStatement(builder.toString())) {
 967 
 968             for (int i = 0; i < addValues.size(); i++) {
 969                 SqlColumn sqlColumn = addValues.get(i);
 970                 Object invoke = sqlColumn.getGetMethod().invoke(obj);
 971                 setStmtParams(prepareStatement, sqlColumn, i + 1, invoke);
 972             }
 973 
 974             for (int i = 0; i < keyValues.size(); i++) {
 975                 SqlColumn sqlColumn = keyValues.get(i);
 976                 Object invoke = sqlColumn.getGetMethod().invoke(obj);
 977                 setStmtParams(prepareStatement, sqlColumn, addValues.size() + i + 1, invoke);
 978             }
 979             int executeUpdate = prepareStatement.executeUpdate();
 980             if (showSql) {
 981                 log.error("\n" + prepareStatement.toString() + " 执行结果:" + executeUpdate);
 982             }
 983             if (executeUpdate <= 0) {
 984                 return false;
 985             }
 986         }
 987         return true;
 988     }
 989     //</editor-fold>
 990 
 991     //<editor-fold defaultstate="collapsed" desc="更新数据 public int executeUpdate(String sql, Object... objs)">
 992     /**
 993      * 更新数据
 994      *
 995      * @param sql
 996      * @param objs
 997      * @return
 998      * @throws SQLException
 999      * @throws ClassNotFoundException
1000      * @throws IOException
1001      */
1002     public int executeUpdate(String sql, Object... objs) throws SQLException, ClassNotFoundException, IOException {
1003         Connection con = getConnection();
1004         try (PreparedStatement prepareStatement = con.prepareStatement(sql)) {
1005             if (objs != null && objs.length > 0) {
1006                 for (int i = 0; i < 10; i++) {
1007                     setStmtParams(prepareStatement, i + 1, objs[i]);
1008                 }
1009             }
1010             int executeUpdate = prepareStatement.executeUpdate();
1011             if (showSql) {
1012                 log.error("\n" + prepareStatement.toString() + " 执行结果:" + executeUpdate);
1013             }
1014             return executeUpdate;
1015         }
1016     }
1017     //</editor-fold>
1018 
1019     //<editor-fold defaultstate="collapsed" desc="删除数据 public int delete(Class<?> clazz)">
1020     /**
1021      * 删除数据
1022      *
1023      * @param clazz
1024      * @return
1025      * @throws SQLException
1026      * @throws ClassNotFoundException
1027      * @throws IOException
1028      */
1029     public int delete(Class<?> clazz) throws SQLException, ClassNotFoundException, IOException {
1030         return delete(clazz, null);
1031     }
1032     //</editor-fold>
1033 
1034     //<editor-fold defaultstate="collapsed" desc="删除行 public int delete(Class<?> clazz, String sqlWhere, Object... objs)">
1035     /**
1036      * 删除行
1037      *
1038      * @param clazz
1039      * @param sqlWhere
1040      * @param objs
1041      * @return
1042      * @throws SQLException
1043      * @throws ClassNotFoundException
1044      * @throws IOException
1045      */
1046     public int delete(Class<?> clazz, String sqlWhere, Object... objs) throws SQLException, ClassNotFoundException, IOException {
1047         StringBuilder builder = new StringBuilder();
1048         String tableName = getTableName(clazz);
1049         builder.append("DELETE FROM `").append(tableName).append("`");
1050         if (!StringUtil.isNullOrEmpty(sqlWhere)) {
1051             builder.append(" WHERE ").append(sqlWhere);
1052         }
1053         return executeUpdate(builder.toString(), objs);
1054     }
1055     //</editor-fold>
1056 
1057     //<editor-fold defaultstate="collapsed" desc="删除表 public int dropTable(Object obj)">
1058     /**
1059      * 删除表
1060      *
1061      * @param obj
1062      * @return
1063      * @throws SQLException
1064      * @throws ClassNotFoundException
1065      * @throws IOException
1066      */
1067     public int dropTable(Object obj) throws SQLException, ClassNotFoundException, IOException {
1068         return dropTable(obj.getClass());
1069     }
1070     //</editor-fold>
1071 
1072     //<editor-fold defaultstate="collapsed" desc="删除表 public int dropTable(Class<?> clazz)">
1073     /**
1074      * 删除表
1075      *
1076      * @param clazz
1077      * @return
1078      * @throws SQLException
1079      * @throws ClassNotFoundException
1080      * @throws IOException
1081      */
1082     public int dropTable(Class<?> clazz) throws SQLException, ClassNotFoundException, IOException {
1083         StringBuilder builder = new StringBuilder();
1084         String tableName = getTableName(clazz);
1085         builder.append("DROP TABLE IF EXISTS `").append(tableName).append("`;");
1086         return executeUpdate(builder.toString());
1087     }
1088     //</editor-fold>
1089 
1090     //<editor-fold defaultstate="collapsed" desc="删除数据库 public int dropDatabase(String database)">
1091     /**
1092      * 删除数据库
1093      *
1094      * @param database
1095      * @return
1096      * @throws SQLException
1097      * @throws ClassNotFoundException
1098      * @throws IOException
1099      */
1100     public int dropDatabase(String database) throws SQLException, ClassNotFoundException, IOException {
1101         StringBuilder builder = new StringBuilder();
1102         builder.append("DROP DATABASE IF EXISTS `").append(database).append("`;");
1103         return executeUpdate(builder.toString());
1104     }
1105     //</editor-fold>
1106 
1107     //<editor-fold defaultstate="collapsed" desc="创建数据库 public int createDatabase(String database)">
1108     /**
1109      * 创建数据库 , 吃方法创建数据库后会自动使用 use 语句
1110      *
1111      * @param database
1112      * @return
1113      * @throws SQLException
1114      * @throws ClassNotFoundException
1115      * @throws IOException
1116      */
1117     public int createDatabase(String database) throws SQLException, ClassNotFoundException, IOException {
1118         StringBuilder builder = new StringBuilder();
1119         builder.append("CREATE DATABASE IF NOT EXISTS `").append(database).append("` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;");
1120         int executeUpdate = executeUpdate(builder.toString());
1121         builder = new StringBuilder();
1122         builder.append("use `").append(database).append("`;");;
1123         executeUpdate(builder.toString());
1124         return executeUpdate;
1125     }
1126     //</editor-fold>
1127 
1128 }

由于我们存在mysql和sqlite的版本,这里抽象出来了base class

  1 package net.sz.engine.db;
  2 
  3 import java.io.IOException;
  4 import java.sql.Connection;
  5 import java.sql.DriverManager;
  6 import java.sql.PreparedStatement;
  7 import java.sql.ResultSet;
  8 import java.sql.SQLException;
  9 import java.sql.Statement;
 10 import java.util.List;
 11 import org.apache.log4j.Logger;
 12 
 13 /**
 14  *
 15  * <br>
 16  * author 失足程序员<br>
 17  * mail 492794628@qq.com<br>
 18  * phone 13882122019<br>
 19  */
 20 public class MysqlDaoImp1 extends Dao {
 21 
 22     private static final Logger log = Logger.getLogger(MysqlDaoImp1.class);
 23 
 24     public MysqlDaoImp1(String dbUrl, String dbName, String dbUser, String dbPwd, boolean showSql) {
 25         super(dbUrl, dbName, dbUser, dbPwd, showSql);
 26     }
 27     private Connection _con = null;
 28 
 29     /**
 30      * 获取数据库的连接
 31      *
 32      * @return
 33      * @throws java.sql.SQLException
 34      * @throws java.lang.ClassNotFoundException
 35      */
 36     @Override
 37     protected Connection getConnection() throws SQLException, ClassNotFoundException {
 38         if (_con != null && !_con.isClosed()) {
 39             return _con;
 40         }
 41         try {
 42             if (_con != null) {
 43                 _con.close();
 44             }
 45         } catch (Exception e) {
 46             log.error("", e);
 47         }
 48         try {
 49             Class.forName("com.mysql.jdbc.Driver");
 50         } catch (ClassNotFoundException e) {
 51         }
 52         try {
 53             Class.forName("com.mysql.cj.jdbc.Driver");
 54         } catch (ClassNotFoundException e) {
 55         }
 56         _con = DriverManager.getConnection("jdbc:mysql://" + dbUrl + "/" + dbName, dbUser, dbPwd);
 57         return _con;
 58     }
 59 
 60     @Override
 61     public boolean existsTable(String tableName) throws SQLException, IOException, ClassNotFoundException {
 62         String ifexits = "select sum(1) `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` where `TABLE_SCHEMA`='" + dbName + "' and `TABLE_NAME`='" + tableName + "' ;";
 63         Connection con = getConnection();
 64         try (PreparedStatement createStatement = con.prepareStatement(ifexits)) {
 65             ResultSet executeQuery = createStatement.executeQuery();
 66             if (executeQuery != null && executeQuery.next()) {
 67                 int aInt = executeQuery.getInt("TABLE_NAME");
 68                 if (showSql) {
 69                     log.error("表:" + tableName + " 检查结果:" + (aInt > 0 ? " 已经存在 " : " 无此表 "));
 70                 }
 71                 if (aInt > 0) {
 72                     return true;
 73                 }
 74             }
 75         }
 76         return false;
 77     }
 78 
 79     /**
 80      *
 81      * @param o
 82      * @param tableName
 83      * @param columns
 84      * @throws SQLException
 85      * @throws IOException
 86      * @throws ClassNotFoundException
 87      */
 88     @Override
 89     protected void createTable(Object o, String tableName, List<SqlColumn> columns) throws SQLException, IOException, ClassNotFoundException {
 90         if (existsTable(tableName)) {
 91             //执行对应的创建表操作
 92             Connection con = getConnection();
 93             if (showSql) {
 94                 log.error("表" + tableName + "已经存在,检测字段变更,只会处理新增字段;");
 95             }
 96             for (SqlColumn value : columns) {
 97                 String ifexits = "SELECT sum(1) usm FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='" + dbName + "' AND table_name='" + tableName + "' AND COLUMN_NAME='" + value.getColumnName() + "'";
 98                 try (Statement createStatement = con.createStatement()) {
 99                     ResultSet executeQuery = createStatement.executeQuery(ifexits);
100                     if (executeQuery != null && executeQuery.next()) {
101                         int aInt = executeQuery.getInt("usm");
102                         if (aInt == 0) {
103                             if (showSql) {
104                                 log.error("表:" + tableName + " 字段:" + value.getFieldName() + " 映射数据库字段:" + value.getColumnName() + " 不存在,");
105                             }
106                             String sqls = "ALTER TABLE `" + tableName + "` ADD `" + value.getColumnName() + "` " + value.getValue() + ";";
107                             boolean execute1 = createStatement.execute(sqls);
108                             if (showSql) {
109                                 log.error("执行语句:" + sqls + " 执行结果:" + execute1);
110                             }
111                         } else {
112                             if (showSql) {
113                                 log.error("表:" + tableName + " 字段:" + value.getFieldName() + " 映射数据库字段:" + value.getColumnName() + " 存在,将不会修改");
114                             }
115                             /*   String sqls = "ALTER TABLE " + tableName + " CHANGE `" + key + "` " + value.getValue() + ";";
116                                     if (showSql) {
117                                         log.error("执行语句:" + sqls);
118                                     }
119                                     try (Statement cs1 = con.createStatement()) {
120                                         boolean execute1 = cs1.execute(sqls);
121                                         if (showSql) {
122                                             log.error("执行结果:" + execute1);
123                                         }
124                                     }*/
125                         }
126                     }
127                 }
128             }
129         } else {
130             StringBuilder sb = new StringBuilder();
131             sb.append("\n create table if not exists `").append(tableName).append("` (\n");
132             //将所有的字段拼接成对应的SQL语句
133             for (SqlColumn sqlColumn : columns) {
134                 sb.append("     `").append(sqlColumn.getColumnName()).append("` ").append(sqlColumn.getValue()).append(" COMMENT '").append(sqlColumn.getColumnDefinition()).append("' ").append(",\n");
135             }
136             sb.delete(sb.length() - 2, sb.length());
137             sb.append("\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
138             //执行对应的创建表操作
139             String sql = sb.toString();
140             Connection con = getConnection();
141             try (PreparedStatement p1 = con.prepareStatement(sql)) {
142                 boolean execute = p1.execute();
143                 if (showSql) {
144                     log.error("\n表:" + sql + "\n 创建完成;");
145                 }
146             }
147         }
148     }
149 }

sqlite 数据库支持

  1 package net.sz.engine.db;
  2 
  3 import java.io.IOException;
  4 import java.sql.Connection;
  5 import java.sql.DriverManager;
  6 import java.sql.PreparedStatement;
  7 import java.sql.ResultSet;
  8 import java.sql.SQLException;
  9 import java.sql.Statement;
 10 import java.util.List;
 11 import org.apache.log4j.Logger;
 12 
 13 /**
 14  * 尚未完善的数据集合
 15  * <br>
 16  * author 失足程序员<br>
 17  * mail 492794628@qq.com<br>
 18  * phone 13882122019<br>
 19  */
 20 public class SqliteDaoImp1 extends Dao {
 21 
 22     private static final Logger log = Logger.getLogger(SqliteDaoImp1.class);
 23 
 24     public SqliteDaoImp1(String dbUrl, String dbName, String dbUser, String dbPwd, boolean showSql) {
 25         super(dbUrl, dbName, dbUser, dbPwd, showSql);
 26     }
 27 
 28     private Connection _con = null;
 29 
 30     /**
 31      * 获取数据库的连接
 32      *
 33      * @return
 34      * @throws java.sql.SQLException
 35      * @throws java.lang.ClassNotFoundException
 36      */
 37     @Override
 38     protected Connection getConnection() throws SQLException, ClassNotFoundException {
 39         if (_con != null && !_con.isClosed()) {
 40             return _con;
 41         }
 42         try {
 43             if (_con != null) {
 44                 _con.close();
 45             }
 46         } catch (Exception e) {
 47             log.error("", e);
 48         }
 49         Class.forName("org.sqlite.JDBC");
 50         _con = DriverManager.getConnection("jdbc:sqlite:" + dbName, dbUser, dbPwd);
 51         return _con;
 52     }
 53 
 54     @Override
 55     public boolean existsTable(String tableName) throws SQLException, IOException, ClassNotFoundException {
 56         String ifexits = "select sum(1) `TABLE_NAME` from sqlite_master where type ='table' and `name`='" + tableName + "' ;";
 57         Connection con = getConnection();
 58         try (PreparedStatement createStatement = con.prepareStatement(ifexits)) {
 59             ResultSet executeQuery = createStatement.executeQuery();
 60             if (executeQuery != null && executeQuery.next()) {
 61                 int aInt = executeQuery.getInt("TABLE_NAME");
 62                 if (showSql) {
 63                     log.error("表:" + tableName + " 检查结果:" + (aInt > 0 ? " 已经存在 " : " 无此表 "));
 64                 }
 65                 if (aInt > 0) {
 66                     return true;
 67                 }
 68             }
 69         }
 70         return false;
 71     }
 72 
 73     /**
 74      *
 75      * @param o
 76      * @param tableName
 77      * @param columns
 78      * @throws SQLException
 79      * @throws IOException
 80      * @throws ClassNotFoundException
 81      */
 82     @Override
 83     protected void createTable(Object o, String tableName, List<SqlColumn> columns) throws SQLException, IOException, ClassNotFoundException {
 84         if (existsTable(tableName)) {
 85             //执行对应的创建表操作
 86             Connection con = getConnection();
 87             if (showSql) {
 88                 log.error("表" + tableName + "已经存在,检测字段变更,只会处理新增字段;");
 89             }
 90             for (SqlColumn value : columns) {
 91                 String ifexits = "SELECT sum(1) usm FROM sqlite_master WHERE name='" + tableName + "' AND sql like '%" + value.getColumnName() + "%'";
 92                 try (Statement createStatement = con.createStatement()) {
 93                     ResultSet executeQuery = createStatement.executeQuery(ifexits);
 94                     if (executeQuery != null && executeQuery.next()) {
 95                         int aInt = executeQuery.getInt("usm");
 96                         if (aInt == 0) {
 97                             if (showSql) {
 98                                 log.error("表:" + tableName + " 字段:" + value.getFieldName() + " 映射数据库字段:" + value.getColumnName() + " 不存在,");
 99                             }
100                             String sqls = "ALTER TABLE `" + tableName + "` ADD `" + value.getColumnName() + "` " + value.getValue() + ";";
101                             int execute1 = createStatement.executeUpdate(sqls);
102                             if (showSql) {
103                                 log.error("执行语句:" + sqls + " 执行结果:" + execute1);
104                             }
105                         } else {
106                             if (showSql) {
107                                 log.error("表:" + tableName + " 字段:" + value.getFieldName() + " 映射数据库字段:" + value.getColumnName() + " 存在,将不会修改");
108                             }
109                             /*   String sqls = "ALTER TABLE " + tableName + " CHANGE `" + key + "` " + value.getValue() + ";";
110                                     if (showSql) {
111                                         log.error("执行语句:" + sqls);
112                                     }
113                                     try (Statement cs1 = con.createStatement()) {
114                                         boolean execute1 = cs1.execute(sqls);
115                                         if (showSql) {
116                                             log.error("执行结果:" + execute1);
117                                         }
118                                     }*/
119                         }
120                     }
121                 }
122             }
123         } else {
124             StringBuilder sb = new StringBuilder();
125             sb.append("\n create table if not exists `").append(tableName).append("` (\n");
126             //将所有的字段拼接成对应的SQL语句
127             for (SqlColumn value : columns) {
128                 sb.append("     `").append(value.getColumnName()).append("` ").append(value.getValue()).append(",\n");
129             }
130             sb.delete(sb.length() - 2, sb.length());
131             sb.append("\n);");
132             //执行对应的创建表操作
133             String sql = sb.toString();
134             Connection con = getConnection();
135             try (PreparedStatement p1 = con.prepareStatement(sql)) {
136                 int execute = p1.executeUpdate();
137                 if (showSql) {
138                     log.error("\n表:" + sql + " \n创建完成;");
139                 }
140             }
141         }
142     }
143 
144     @Override
145     public int createDatabase(String database) throws SQLException, ClassNotFoundException, IOException {
146         throw new UnsupportedOperationException("Create Database do not Operation");
147     }
148 
149     @Override
150     public int dropDatabase(String database) throws SQLException, ClassNotFoundException, IOException {
151         throw new UnsupportedOperationException("Drop Database do not Operation");
152     }
153 
154 }

在实体模型解析上面需求的辅助类

  1 package net.sz.engine.db;
  2 
  3 import java.lang.reflect.Method;
  4 import org.apache.log4j.Logger;
  5 
  6 /**
  7  *
  8  * <br>
  9  * author 失足程序员<br>
 10  * mail 492794628@qq.com<br>
 11  * phone 13882122019<br>
 12  */
 13 class SqlColumn {
 14 
 15     private static final Logger log = Logger.getLogger(SqlColumn.class);
 16     //数据库映射名字
 17     private String columnName;
 18     //字段名字
 19     private String fieldName;
 20     //字段长度
 21     private int colunmLength;
 22     //是否是自增列表
 23     private boolean columnAuto;
 24     //是否是主键列
 25     private boolean columnkey;
 26     //字段是否为空
 27     private boolean columnNullAble;
 28     //字段描述
 29     private String columnDefinition;
 30     //最后拼接
 31     private String value;
 32     //
 33     private Class<?> classType;
 34 
 35     private Method setMethod;
 36 
 37     private Method getMethod;
 38 
 39     public SqlColumn() {
 40         this.columnName = "";
 41         this.fieldName = "";
 42         this.colunmLength = 255;
 43         this.columnAuto = false;
 44         this.columnkey = false;
 45         this.columnNullAble = true;
 46         this.columnDefinition = "";
 47     }
 48 
 49     public String getFieldName() {
 50         return fieldName;
 51     }
 52 
 53     public void setFieldName(String fieldName) {
 54         this.fieldName = fieldName;
 55     }
 56 
 57     public Class<?> getClassType() {
 58         return classType;
 59     }
 60 
 61     public void setClassType(Class<?> classType) {
 62         this.classType = classType;
 63     }
 64 
 65     public String getColumnName() {
 66         return columnName;
 67     }
 68 
 69     public void setColumnName(String columnName) {
 70         this.columnName = columnName;
 71     }
 72 
 73     public int getColunmLength() {
 74         return colunmLength;
 75     }
 76 
 77     public void setColunmLength(int colunmLength) {
 78         this.colunmLength = colunmLength;
 79     }
 80 
 81     public boolean isColumnAuto() {
 82         return columnAuto;
 83     }
 84 
 85     public void setColumnAuto(boolean columnAuto) {
 86         this.columnAuto = columnAuto;
 87     }
 88 
 89     public boolean isColumnkey() {
 90         return columnkey;
 91     }
 92 
 93     public void setColumnkey(boolean columnkey) {
 94         this.columnkey = columnkey;
 95     }
 96 
 97     public boolean isColumnNullAble() {
 98         return columnNullAble;
 99     }
100 
101     public void setColumnNullAble(boolean columnNullAble) {
102         this.columnNullAble = columnNullAble;
103     }
104 
105     public String getColumnDefinition() {
106         return columnDefinition;
107     }
108 
109     public void setColumnDefinition(String columnDefinition) {
110         this.columnDefinition = columnDefinition;
111     }
112 
113     public String getValue() {
114         return value;
115     }
116 
117     public void setValue(String value) {
118         this.value = value;
119     }
120 
121     public Method getSetMethod() {
122         return setMethod;
123     }
124 
125     public void setSetMethod(Method setMethod) {
126         this.setMethod = setMethod;
127     }
128 
129     public Method getGetMethod() {
130         return getMethod;
131     }
132 
133     public void setGetMethod(Method getMethod) {
134         this.getMethod = getMethod;
135     }
136 
137     @Override
138     public String toString() {
139         return "SqlColumn{" + "columnName=" + columnName + ", colunmLength=" + colunmLength + ", columnAuto=" + columnAuto + ", columnkey=" + columnkey + ", columnNullAble=" + columnNullAble + ", columnDefinition=" + columnDefinition + ", value=" + value + '}';
140     }
141 
142 }

测试情况:

  1 package net.sz.engine.db;
  2 
  3 import org.apache.log4j.Logger;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 import javax.persistence.Column;
  8 import javax.persistence.Id;
  9 import javax.persistence.Table;
 10 
 11 /**
 12  * 反射自动查询和封装的类
 13  * <br>
 14  * author 失足程序员<br>
 15  * mail 492794628@qq.com<br>
 16  * phone 13882122019<br>
 17  */
 18 public class TestDao {
 19 
 20     private static final Logger log = Logger.getLogger(TestDao.class);
 21 
 22     public static void main(String[] args) throws Exception {
 23         //====================添加======================
 24 //        Dog d = new Dog(21, "小不点", "藏獒", "灰色", 25);
 25         Person p = new Person(64, "大象hadoop", 10, "家住Apache基金组织");
 26         p.getMap().put("s", "s");
 27         Person p1 = new Person(65, "xxxx", 10, "家住Apache基金组织");
 28         p1.getMap().put("s", "s");
 29         Dao mysqlps = new MysqlDaoImp1("192.168.2.220:3306", "test", "root", "1qaz2wsx", true);
 30         Dao sqliteps = new SqliteDaoImp1("", "log.db", "root", "1qaz2wsx", true);
 31 
 32         mysqlps.dropDatabase("test");
 33         mysqlps.createDatabase("test");
 34 //        mysqlps.dropTable(p);
 35         mysqlps.createTable(p);
 36         mysqlps.delete(p.getClass());
 37         mysqlps.addInsertSql(p, p1);
 38 
 39 //        sqliteps.dropDatabase("test");
 40 //        sqliteps.createDatabase("test");
 41 //        sqliteps.dropTable(p);
 42         sqliteps.createTable(p);
 43         sqliteps.delete(p.getClass());
 44         sqliteps.addInsertSql(p, p1);
 45         List<? extends Person> list = mysqlps.getList(p.getClass(), null);
 46         for (Person person : list) {
 47             log.error(person.toString());
 48         }
 49         mysqlps.update(p1);
 50         sqliteps.update(p1);
 51 //        =======================查询=======================
 52 //        强制转换为原始类
 53 //    Dog d1=(Dog)getOneObject("com.qin.model.Dog", "id", "1");
 54 //    log.debug(d1);
 55 //        Person d1 = (Person) getOneObject(Person.class.getName(), "id", "1");
 56 //        Person d1=(Person)getOneObject("com.qin.model.Person", "name", "王婷");
 57 //        log.debug(d1);
 58     }
 59 
 60 }
 61 
 62 /**
 63  *
 64  * <br>
 65  * author 失足程序员<br>
 66  * mail 492794628@qq.com<br>
 67  * phone 13882122019<br>
 68  */
 69 @Table(name = "Person")
 70 class Person {
 71 
 72     private static final Logger log = Logger.getLogger(Person.class);
 73 
 74     @Id
 75     @Column(name = "_id")
 76     private int id;
 77 
 78     @Column(name = "dName", length = 655)
 79     private String name;
 80 
 81     private int age;
 82     private Short age1;
 83     private Byte age2;
 84     private String address;
 85 
 86     @Column(nullable = false)
 87     private Map<String, String> map = new HashMap<>();
 88 
 89     public Person() {
 90         // TODO Auto-generated constructor stub
 91     }
 92 
 93     public Person(int id, String name, int age, String address) {
 94         super();
 95         this.id = id;
 96         this.name = name;
 97         this.age = age;
 98         this.address = address;
 99     }
100 
101     public int getId() {
102         return id;
103     }
104 
105     public void setId(int id) {
106         this.id = id;
107     }
108 
109     public String getName() {
110         return name;
111     }
112 
113     public void setName(String name) {
114         this.name = name;
115     }
116 
117     public int getAge() {
118         return age;
119     }
120 
121     public void setAge(int age) {
122         this.age = age;
123     }
124 
125     public String getAddress() {
126         return address;
127     }
128 
129     public void setAddress(String address) {
130         this.address = address;
131     }
132 
133     public Map<String, String> getMap() {
134         return map;
135     }
136 
137     public void setMap(Map<String, String> map) {
138         this.map = map;
139     }
140 
141     public Short getAge1() {
142         return age1;
143     }
144 
145     public void setAge1(Short age1) {
146         this.age1 = age1;
147     }
148 
149     public Byte getAge2() {
150         return age2;
151     }
152 
153     public void setAge2(Byte age2) {
154         this.age2 = age2;
155     }
156 
157     @Override
158     public String toString() {
159         return "Person{" + "id=" + id + ", name=" + name + ", age=" + age + ", age1=" + age1 + ", age2=" + age2 + ", address=" + address + ", map=" + map + '}';
160     }
161 
162 }
 1 --- exec-maven-plugin:1.2.1:exec (default-cli) @ net.sz.game.engine ---
 2 [11-04 15:27:11:0938:ERROR: db.Dao.executeUpdate():1012] -> 
 3 com.mysql.jdbc.JDBC42PreparedStatement@7c53a9eb: DROP DATABASE IF EXISTS `test`; 执行结果:1
 4 [11-04 15:27:11:0943:ERROR: db.Dao.executeUpdate():1012] -> 
 5 com.mysql.jdbc.JDBC42PreparedStatement@2f333739: CREATE DATABASE IF NOT EXISTS `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; 执行结果:1
 6 [11-04 15:27:11:0944:ERROR: db.Dao.executeUpdate():1012] -> 
 7 com.mysql.jdbc.JDBC42PreparedStatement@12bb4df8: use `test`; 执行结果:0
 8 [11-04 15:27:11:0953:ERROR: db.Dao.getColumns():305] -> 类:net.sz.engine.db.Person 字段:log is transient or static or final;
 9 [11-04 15:27:11:0962:ERROR: db.MysqlDaoImp1.existsTable():69 ] -> 表:Person 检查结果: 无此表 
10 [11-04 15:27:12:0138:ERROR: db.MysqlDaoImp1.createTable():144] -> 
11 表:
12  create table if not exists `Person` (
13      `_id` int(4) not null primary key COMMENT '' ,
14      `dName` varchar(655) null COMMENT '' ,
15      `age` int(4) null COMMENT '' ,
16      `age1` tinyint(2) null COMMENT '' ,
17      `age2` tinyint(1) null COMMENT '' ,
18      `address` varchar(255) null COMMENT '' ,
19      `map` blob not null COMMENT '' 
20 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
21  创建完成;
22 [11-04 15:27:12:0141:ERROR: db.Dao.executeUpdate():1012] -> 
23 com.mysql.jdbc.JDBC42PreparedStatement@27ddd392: DELETE FROM `Person` 执行结果:0
24 [11-04 15:27:12:0143:ERROR: db.MysqlDaoImp1.existsTable():69 ] -> 表:Person 检查结果: 已经存在 
25 [11-04 15:27:12:0188:ERROR: db.Dao.addInsertSql():652] -> 执行 com.mysql.jdbc.JDBC42PreparedStatement@2db0f6b2: insert into `Person` (`_id`, `dName`, `age`, `age1`, `age2`, `address`, `map`) values 
26 (64, '大象hadoop', 10, null, null, '家住Apache基金组织', x'ACED0005737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000017400017371007E000278' ),
27 (65, 'xxxx', 10, null, null, '家住Apache基金组织', x'ACED0005737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000017400017371007E000278' ); 添加数据 表:Person 结果 影响行数:2
28 [11-04 15:27:12:0356:ERROR: db.SqliteDaoImp1.existsTable():63 ] -> 表:Person 检查结果: 已经存在 
29 [11-04 15:27:12:0356:ERROR: db.SqliteDaoImp1.createTable():88 ] -> 表Person已经存在,检测字段变更,只会处理新增字段;
30 [11-04 15:27:12:0356:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:id 映射数据库字段:_id 存在,将不会修改
31 [11-04 15:27:12:0357:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:name 映射数据库字段:dName 存在,将不会修改
32 [11-04 15:27:12:0357:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:age 映射数据库字段:age 存在,将不会修改
33 [11-04 15:27:12:0357:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:age1 映射数据库字段:age1 存在,将不会修改
34 [11-04 15:27:12:0358:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:age2 映射数据库字段:age2 存在,将不会修改
35 [11-04 15:27:12:0360:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:address 映射数据库字段:address 存在,将不会修改
36 [11-04 15:27:12:0361:ERROR: db.SqliteDaoImp1.createTable():107] -> 表:Person 字段:map 映射数据库字段:map 存在,将不会修改
37 [11-04 15:27:12:0386:ERROR: db.Dao.executeUpdate():1012] -> 
38 org.sqlite.jdbc4.JDBC4PreparedStatement@66d33a 执行结果:2
39 [11-04 15:27:12:0386:ERROR: db.SqliteDaoImp1.existsTable():63 ] -> 表:Person 检查结果: 已经存在 
40 [11-04 15:27:12:0401:ERROR: db.Dao.addInsertSql():652] -> 执行 org.sqlite.jdbc4.JDBC4PreparedStatement@7cf10a6f 添加数据 表:Person 结果 影响行数:2
41 [11-04 15:27:12:0401:ERROR: db.Dao.getResultSet():777] -> 
42 com.mysql.jdbc.JDBC42PreparedStatement@7e0babb1: SELECT `_id`,`dName`,`age`,`age1`,`age2`,`address`,`map` FROM `Person` 
43 [11-04 15:27:12:0406:ERROR: db.TestDao.main():47 ] -> Person{id=64, name=大象hadoop, age=10, age1=null, age2=null, address=家住Apache基金组织, map={s=s}}
44 [11-04 15:27:12:0406:ERROR: db.TestDao.main():47 ] -> Person{id=65, name=xxxx, age=10, age1=null, age2=null, address=家住Apache基金组织, map={s=s}}
45 [11-04 15:27:12:0438:ERROR: db.Dao.update():981] -> 
46 com.mysql.jdbc.JDBC42PreparedStatement@c818063: update `Person` set `dName` = 'xxxx', `age` = 10, `age1` = null, `age2` = null, `address` = '家住Apache基金组织', `map` = x'ACED0005737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000017400017371007E000278' where  `_id` = 65  执行结果:1
47 [11-04 15:27:12:0452:ERROR: db.Dao.update():981] -> 
48 org.sqlite.jdbc4.JDBC4PreparedStatement@75bd9247 执行结果:1
49 ------------------------------------------------------------------------
50 BUILD SUCCESS
51 ------------------------------------------------------------------------
52 Total time: 2.299s
53 Finished at: Fri Nov 04 15:27:12 CST 2016
54 Final Memory: 7M/238M
55 ------------------------------------------------------------------------

 

由于这是出版的,并没有加入连接池,批量修改,和事务的处理;

想喷的尽管喷。

有什么建议和意见的也尽管提;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值