zoukankan      html  css  js  c++  java
  • Vertx Mysql数据库优化 (七)

    项目github地址:https://github.com/fotocj007/VertxWebApi

    前一章节完成了mysql客户端的链接和基本重新,每次重新都需要写sql语句,这章优化一下mysql的一些基本处理。

    优先将实体加载到内存中,需要进行mysql操作时直接读取,不需要每次都写sql语句。

    一:定义一些注解

    1 //定义主键
    2 @Documented
    3 @Target({ElementType.FIELD})
    4 @Retention(RetentionPolicy.RUNTIME)
    5 public @interface Id {
    6 }
    View Code
    1 //定义表
    2 @Documented
    3 @Target({ElementType.TYPE})
    4 @Retention(RetentionPolicy.RUNTIME)
    5 public @interface Table {
    6     String name() default "";
    7 }
    View Code
    1 //定义需要忽略的字段--实体类有,数据库没有的字段
    2 @Documented
    3 @Target({ElementType.FIELD})
    4 @Retention(RetentionPolicy.RUNTIME)
    5 public @interface Transient {
    6 }
    View Code
    1 //定义主键是否自动递增
    2 @Documented
    3 @Target({ElementType.FIELD})
    4 @Retention(RetentionPolicy.RUNTIME)
    5 public @interface GeneratedValue {
    6 }
    View Code

    二:定义实体类的抽象基类

     1 /**
     2  *
     3  * @param <ID> 主键
     4  * @param <K>  查询key名称
     5  */
     6 
     7 public abstract class BaseEntity<ID extends Serializable,K extends Serializable> {
     8     public abstract ID getId();
     9 
    10     public abstract void setId(ID id);
    11     // 分库分表依赖id
    12     public abstract K splitId();
    13 }
    View Code

    三:解析注解--重要类

      1 public class MysqlDbDao {
      2     protected Logger logger = LoggerFactory.getLogger(MysqlDbDao.class);
      3 
      4     protected MySQLUtil mySQLPool;
      5 
      6     protected String DB_SPLIT = "";
      7     // 表名
      8     protected Map<Class,String> tableMap;
      9     // 主键名
     10     protected Map<Class,String> primaryKeyMap;
     11     // insert字段列表
     12     protected Map<Class, List<String>> insertFieldMap;
     13     // insert sql
     14     protected Map<Class,String> insertSqlMap;
     15     //  update字段列表
     16     protected Map<Class,List<String>> updateFieldMap;
     17     //  update sql
     18     protected Map<Class,String> updateSqlMap;
     19 
     20     public MysqlDbDao(String DB_SPLIT,MySQLUtil mySQLPool){
     21         this.DB_SPLIT = DB_SPLIT;
     22         this.mySQLPool = mySQLPool;
     23         tableMap = new HashMap<>();
     24         primaryKeyMap = new HashMap<>();
     25         insertFieldMap = new HashMap<>();
     26         insertSqlMap = new HashMap<>();
     27         updateFieldMap = new HashMap<>();
     28         updateSqlMap = new HashMap<>();
     29     }
     30 
     31     /*************************
     32      * 加载分库分表的一些基本信息
     33      * 实体类的表,主键,更新和插入的字段(实体类的字段)
     34      */
     35     public void loadAllDBInfo(List<String> fileList){
     36         try{
     37             for(String fileName : fileList){
     38                 Class classes = Class.forName(fileName);
     39                 tableMap.put(classes,getTableName(fileName));
     40                 primaryKeyMap.put(classes,getUpdatePrimaryKey(fileName));
     41                 insertFieldMap.put(classes,getInsertFiled(fileName));
     42                 insertSqlMap.put(classes,getInsertSql(fileName));
     43                 updateFieldMap.put(classes,getUpdateFiled(fileName));
     44                 updateSqlMap.put(classes,getUpdateSql(fileName));
     45             }
     46         }catch (Exception ex){
     47             throw new RuntimeException(ex);
     48         }
     49     }
     50 
     51     /*************************
     52      * 插入新数据
     53      */
     54     public void saveBaseEntity(BaseEntity entity, Handler<AsyncResult<Long>> handler){
     55         StringBuffer sql = new StringBuffer("insert into ");
     56         sql.append(DB_SPLIT).append(".").append(tableMap.get(entity.getClass())).append(" ")
     57                 .append(insertSqlMap.get(entity.getClass()));
     58         Tuple insertParams = genInsertFieldValues(entity);
     59 
     60         mySQLPool.getConfigClient()
     61                 .preparedQuery(sql.toString())
     62                 .execute(insertParams, ar -> {
     63                     if(ar.succeeded()){
     64                         RowSet<Row> rows = ar.result();
     65                         if(rows.size() > 0){
     66                             long lastInsertId = rows.property(MySQLClient.LAST_INSERTED_ID);
     67                             handler.handle(Future.succeededFuture(lastInsertId));
     68                             return;
     69                         }
     70 
     71                         handler.handle(Future.succeededFuture(0L));
     72                     }else {
     73                         handler.handle(Future.failedFuture(ar.cause()));
     74                         logger.error("saveBaseEntity:"+ JsonObject.mapFrom(entity)+",sql="+sql.toString(),ar.cause());
     75                     }
     76                 });
     77     }
     78 
     79     /*************************
     80      * 更新一条数据
     81      */
     82     public void updateBaseEntity(BaseEntity entity,Handler<AsyncResult<Long>> handler){
     83         StringBuffer sql = new StringBuffer("update ");
     84         sql.append(DB_SPLIT).append(".").append(tableMap.get(entity.getClass())).append(" ")
     85                 .append(updateSqlMap.get(entity.getClass()));
     86         Tuple updateParams = genUpdateFieldValues(entity);
     87 
     88         mySQLPool.getConfigClient()
     89                 .preparedQuery(sql.toString())
     90                 .execute(updateParams,saveRes -> {
     91                     if(saveRes.succeeded()){
     92                         long num = saveRes.result().size();
     93                         handler.handle(Future.succeededFuture(num));
     94                     }else {
     95                         handler.handle(Future.failedFuture(saveRes.cause()));
     96                         logger.error("updateBaseEntity:"+JsonObject.mapFrom(entity)+",sql="+sql.toString(),saveRes.cause());
     97                     }
     98                 });
     99     }
    100 
    101     @SuppressWarnings("unchecked")
    102     private String getTableName(String bean) {
    103         try {
    104             Class clz = Class.forName(bean);
    105             boolean annotationPresent = clz.isAnnotationPresent(Table.class);
    106             if (annotationPresent) {
    107                 Table table = (Table) clz.getAnnotation(Table.class);
    108                 return table.name();
    109             }
    110         } catch (ClassNotFoundException e) {
    111             e.printStackTrace();
    112             return null;
    113         }
    114         return "";
    115     }
    116 
    117     /*************************
    118      * 获取更新sql的字符串
    119      */
    120     private String getUpdateSql(String bean) {
    121         StringBuilder sb = new StringBuilder();
    122         sb.append(" set ");
    123         List<String> fieldList = getUpdateFiled(bean);
    124         for(String str : fieldList) {
    125             sb.append(str.split(",")[0]).append("=?,");
    126         }
    127         sb.deleteCharAt(sb.toString().lastIndexOf(","));
    128         sb.append(" where ");
    129         String primaryKey = getUpdatePrimaryKey(bean);
    130         sb.append(primaryKey.split(",")[0]).append("=? ");
    131         return sb.toString();
    132     }
    133 
    134     /*************************
    135      * 获取跟新sql的字段
    136      */
    137     private List<String> getUpdateFiled(String bean){
    138         List<String> list = new ArrayList<>();
    139         try {
    140             Class clz = Class.forName(bean);
    141             Field[] strs = clz.getDeclaredFields();
    142             for(Field field : strs) {
    143                 if(field.isAnnotationPresent(Transient.class)){
    144                     continue;
    145                 }
    146                 String protype =  field.getType().toString();
    147                 boolean annotationPresent  = field.isAnnotationPresent(Id.class);
    148                 if (!annotationPresent) {
    149                     list.add(field.getName()+","+protype.substring(protype.lastIndexOf(".")+1));
    150                 }
    151             }
    152         }catch (ClassNotFoundException e) {
    153             e.printStackTrace();
    154         }
    155         return list;
    156     }
    157 
    158     /*************************
    159      * 跟新sql的主键
    160      */
    161     private String getUpdatePrimaryKey(String bean) {
    162         try {
    163             Class clz = Class.forName(bean);
    164             Field[] strs = clz.getDeclaredFields();
    165             for(Field field : strs) {
    166                 String protype =  field.getType().toString();
    167                 boolean annotationPresent  = field.isAnnotationPresent(Id.class);
    168                 if (annotationPresent) {
    169                     return field.getName()+","+protype.substring(protype.lastIndexOf(".")+1);
    170                 }
    171             }
    172         }catch (ClassNotFoundException e) {
    173             e.printStackTrace();
    174         }
    175 
    176         return "";
    177     }
    178 
    179     /*************************
    180      * 插入新数据的sql字符串
    181      */
    182     private  String getInsertSql(String bean){
    183         StringBuilder sb = new StringBuilder();
    184         sb.append(" (");
    185         List<String> fieldList = getInsertFiled(bean);
    186         for(String str : fieldList) {
    187             sb.append(str.split(",")[0]).append(",");
    188         }
    189         sb.deleteCharAt(sb.toString().lastIndexOf(","));
    190         sb.append(" ) value (");
    191         for(int i = 0;i <fieldList.size();i++) {
    192             if(i == fieldList.size() -1) {
    193                 sb.append("? ");
    194             }else {
    195                 sb.append("?,");
    196             }
    197         }
    198         sb.append(") ");
    199         return sb.toString();
    200     }
    201 
    202     /*************************
    203      * 插入新数据sql的插入字段
    204      */
    205     private List<String> getInsertFiled(String bean){
    206         List<String> list = new ArrayList<>();
    207         try {
    208             Class clz = Class.forName(bean);
    209             Field[] strs = clz.getDeclaredFields();
    210             for(Field field : strs) {
    211                 if(field.isAnnotationPresent(Transient.class)){
    212                     continue;
    213                 }
    214 
    215                 String protype =  field.getType().toString();
    216                 boolean annotationPresent  = field.isAnnotationPresent(Id.class);
    217                 if (annotationPresent) {
    218                     boolean generateAnnotation  = field.isAnnotationPresent(GeneratedValue.class);
    219                     if(!generateAnnotation) {
    220                         list.add(field.getName()+","+protype.substring(protype.lastIndexOf(".")+1));
    221                     }
    222                 }else {
    223                     list.add(field.getName()+","+protype.substring(protype.lastIndexOf(".")+1));
    224                 }
    225             }
    226         }catch (ClassNotFoundException e) {
    227             e.printStackTrace();
    228         }
    229         return list;
    230     }
    231 
    232     /*************************
    233      * 插入新数据sql的值(实体类)
    234      */
    235     protected Tuple genInsertFieldValues(BaseEntity info) {
    236         JsonObject json = JsonObject.mapFrom(info);
    237         String name = "";
    238         String type = "";
    239         List<Object> sb = new ArrayList<>(5);
    240         List<String> fieldList = insertFieldMap.get(info.getClass());
    241         for(String str : fieldList) {
    242             name = str.split(",")[0];
    243             type = str.split(",")[1];
    244             switch (type) {
    245                 case "long":
    246                     sb.add(json.getLong(name,0L));
    247                     break;
    248                 case "int":
    249                 case "byte":
    250                     sb.add(json.getInteger(name,0));
    251                     break;
    252                 case "short":
    253                     sb.add(json.getInteger(name,0).shortValue());
    254                     break;
    255                 case "float":
    256                     sb.add(json.getFloat(name,0f));
    257                     break;
    258                 case "String":
    259                     sb.add(json.getString(name,""));
    260                     break;
    261                 default:
    262                     if(json.getValue(name) != null){
    263                         sb.add(json.getValue(name).toString());
    264                     }else {
    265                         sb.add(json.getValue(""));
    266                     }
    267                     break;
    268             }
    269         }
    270         json = null;
    271 
    272         return Tuple.tuple(sb);
    273     }
    274 
    275     /*************************
    276      * 跟新新数据sql的值(实体类)
    277      */
    278     protected Tuple genUpdateFieldValues(BaseEntity info) {
    279         JsonObject json = JsonObject.mapFrom(info);
    280         String name = "";
    281         String type = "";
    282         List<Object> sb = new ArrayList<>(5);
    283         List<String> fieldList = updateFieldMap.get(info.getClass());
    284         for(String str : fieldList) {
    285             name = str.split(",")[0];
    286             type = str.split(",")[1];
    287             switch (type) {
    288                 case "long":
    289                     sb.add(json.getLong(name,0L));
    290                     break;
    291                 case "int":
    292                 case "byte":
    293                     sb.add(json.getInteger(name,0));
    294                     break;
    295                 case "short":
    296                     sb.add(json.getInteger(name,0).shortValue());
    297                     break;
    298                 case "float":
    299                     sb.add(json.getFloat(name,0f));
    300                     break;
    301                 case "String":
    302                     sb.add(json.getString(name,""));
    303                     break;
    304                 default:
    305                     if(json.getValue(name) != null){
    306                         sb.add(json.getValue(name).toString());
    307                     }else {
    308                         sb.add(json.getValue(""));
    309                     }
    310                     break;
    311             }
    312         }
    313         String primaryKey = primaryKeyMap.get(info.getClass());
    314         name = primaryKey.split(",")[0];
    315         type = primaryKey.split(",")[1];
    316         if(type.equals("long")) {
    317             sb.add(json.getLong(name,0L));
    318         }else if(type.equals("int")) {
    319             sb.add(json.getInteger(name,0));
    320         }else {
    321             sb.add(json.getString(name,""));
    322         }
    323         json = null;
    324         return Tuple.tuple(sb);
    325     }
    326 }
    View Code

    四:调整PlayerInfo实体类

     1 @Table(name = "player_info")
     2 public class PlayerInfo extends BaseEntity<Long,Long>{
     3     @Id
     4     @GeneratedValue
     5     private long id;
     6 
     7     private String userName;
     8 
     9     private int age;
    10 
    11     @Override
    12     public Long getId() {
    13         return id;
    14     }
    15 
    16     @Override
    17     public void setId(Long aLong) {
    18         id = aLong;
    19     }
    20 
    21     @Override
    22     public Long splitId() {
    23         return id;
    24     }
    25 
    26     public void setId(long id) {
    27         this.id = id;
    28     }
    29 
    30     public String getUserName() {
    31         return userName;
    32     }
    33 
    34     public void setUserName(String userName) {
    35         this.userName = userName;
    36     }
    37 
    38     public int getAge() {
    39         return age;
    40     }
    41 
    42     public void setAge(int age) {
    43         this.age = age;
    44     }
    45 }
    View Code

    五:修改PlayerDao帮助类

     1 public class PlayerDao extends MysqlDbDao{
     2     protected Logger logger = LoggerFactory.getLogger(PlayerDao.class);
     3 
     4     public PlayerDao(String DB_SPLIT, MySQLUtil mySQLPool) {
     5         super(DB_SPLIT,mySQLPool);
     6 
     7         loadAllDBInfo();
     8     }
     9 
    10     /*************************
    11      * 加载需要分库分表的实体类
    12      */
    13     private void loadAllDBInfo(){
    14         List<String> classList = new ArrayList<>();
    15         classList.add("com.webser.db.PlayerInfo");
    16 
    17         super.loadAllDBInfo(classList);
    18     }
    19 
    20     /*************************
    21      * 查询数据
    22      * 根据 实体类T获取数据并实例化
    23      */
    24     public <T> void queryConfigList(String sql, Class<T> classes, Handler<AsyncResult<List<T>>> handler){
    25         mySQLPool.getConfigClient().query(sql)
    26                 .execute(qRes -> {
    27                     if(qRes.succeeded()){
    28                         List<T> lists = new ArrayList<>();
    29 
    30                         RowSet<Row> result = qRes.result();
    31                         List<String> col = qRes.result().columnsNames();
    32 
    33                         for (Row row : result) {
    34                             JsonObject json = new JsonObject();
    35                             for (String str : col) {
    36                                 json.put(str,row.getValue(str));
    37                             }
    38                             T entity = new JsonObject(json.toString()).mapTo(classes);
    39                             lists.add(entity);
    40                         }
    41 
    42                         handler.handle(Future.succeededFuture(lists));
    43                     }else {
    44                         handler.handle(Future.failedFuture(qRes.cause()));
    45                         logger.error("--error queryConfigList----- " + sql, qRes.cause());
    46                     }
    47                 });
    48     }
    49 }
    View Code

    六:测试一下

    1:修改DemoHandler

     1 public class DemoHandler implements InterHandler {
     2     @Override
     3     public void handler(AbstractUpMessage up, HttpServerResponse resp) {
     4         //上传参数
     5         DemoRequest request = (DemoRequest)up;
     6         System.out.println("上传参数:"+ request.name + "-" + request.age);
     7 
     8 
     9 //        String sql = "select * from " + Configure.getInstance().mysqlConfig.configDbName + ".player_info ";
    10 //        PlayerDao client = Configure.getInstance().daoManager.getPlayerDao();
    11 //        client.queryConfigList(sql, PlayerInfo.class, res -> {
    12 //            List<PlayerInfo> lists = res.result();
    13 //            for(PlayerInfo item : lists){
    14 //                System.out.println(item.getUserName() + "---" + item.getAge());
    15 //            }
    16 //        });
    17 
    18 
    19         PlayerInfo info = new PlayerInfo();
    20         info.setUserName("kkkkkdd");
    21         info.setAge(100);
    22 
    23         PlayerDao client = Configure.getInstance().daoManager.getPlayerDao();
    24         client.saveBaseEntity(info,res -> {
    25 
    26         });
    27 
    28 
    29         //返回数据
    30         String n = "cscscs---";
    31         String in = "info ---";
    32         //编码返回json
    33         DemoResponse response = new DemoResponse(getMessageId(),n,in);
    34         response.encode();
    35         resp.end(response.SendMessage());
    36     }
    37 
    38     @Override
    39     public short getMessageId() {
    40         return HandlerCode.DEMO_V1;
    41     }
    42 }
    View Code

    2:运行服务端,调用接口

    项目结构

  • 相关阅读:
    【bzoj 1143】[CTSC2008]祭祀river
    【SRM-09 B】撕书II
    【刷题记录】BZOJ-USACO
    【noip 2014】提高组Day2T3.华容道
    【noip 2012】提高组Day2T3.疫情控制
    【noip 2012】提高组Day1T3.开车旅行
    点分治
    2—SAT问题
    生成树
    莫比乌斯反演
  • 原文地址:https://www.cnblogs.com/cj8988/p/15015740.html
Copyright © 2011-2022 走看看