最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java注解實(shí)現(xiàn)自己的ORM

 更新時(shí)間:2022年10月15日 12:01:28   作者:湘王  
這篇文章主要介紹了Java注解實(shí)現(xiàn)自己的ORM知識(shí),本文通過示例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

搞過Java的碼農(nóng)都知道,在J2EE開發(fā)中一個(gè)(確切地說,應(yīng)該是一類)很重要的框架,那就是ORM(Object Relational Mapping,對(duì)象關(guān)系映射)。它把Java中的類和數(shù)據(jù)庫中的表關(guān)聯(lián)起來,可以像操作對(duì)象那樣操作數(shù)據(jù)表,十分方便。給碼農(nóng)們節(jié)約了大量的時(shí)間去摸魚。其實(shí)它的本質(zhì)一點(diǎn)都不復(fù)雜,而最核心的就是怎么實(shí)現(xiàn)對(duì)象和表之間的轉(zhuǎn)換。之前對(duì)反射和注解有了一點(diǎn)了解,所以就試著來實(shí)現(xiàn)咱們自己的縫合怪。

首先,需要建立一個(gè)「表格」:

/**
 * 類注解,將類注解成數(shù)據(jù)庫表
 *
 * @author xiangwang
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
   String name() default "";
}

然后,定義需要的數(shù)據(jù)庫數(shù)據(jù)類型:

/**
 * 字段類型枚舉
 *
 * @author xiangwang
 */
public enum Type {
   CHAR,
   STRING,
   BOOLEAN,
   INTEGER,
   LONG,
   FLOAT,
   DOUBLE,
   DATETIME
}
/**
 * 數(shù)據(jù)庫字段類型
 *
 * @author xiangwang
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnType {
   Type value() default Type.INTEGER;
}

再來完善字段相關(guān)信息:

/**
 * 字段信息
 *
 * @author xiangwang
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtraInfo {
   String name() default "";
   int length() default 0;
}
/**
 * 明確字段約束
 *
 * @author xiangwang
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
    boolean primaryKey() default false;
    boolean allowNull() default true;
    boolean unique() default false;
    // 還可以增加默認(rèn)值
}

把他們拼起來,成為完整的字段描述:

/**
 * 拼裝注解,形成完整的字段嵌套注解
 *
 * @author xiangwang
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableColumn {
   ColumnType columntype() default @ColumnType;
   ExtraInfo extrainfo() default @ExtraInfo;
   Constraints constraints() default @Constraints;
}

最后,創(chuàng)建實(shí)體類,應(yīng)用剛才寫好的這些注解:

/**
 * 用戶實(shí)體類
 *
 * @author xiangwang
 */
@DBTable(name = "User")
public class User {
   @TableColumn(
         columntype = @ColumnType(Type.INTEGER),
         extrainfo = @ExtraInfo(name = "id", length = 4),
         constraints = @Constraints(primaryKey = true))
   private String id;

   @TableColumn(
         columntype = @ColumnType(Type.STRING),
         extrainfo = @ExtraInfo(name = "name", length = 32),
         constraints = @Constraints(primaryKey = false, allowNull = false, unique = true))
   private String name;

   @TableColumn(
         columntype = @ColumnType(Type.INTEGER),
         extrainfo = @ExtraInfo(name = "age", length = 4),
         constraints = @Constraints(primaryKey = false))
   private Integer age;

   public String getId() { return id; }
   public void setId(String id) { this.id = id; }

   public String getName() { return name; }
   public void setName(String name) { this.name = name; }

   public Integer getAge() { return age; }
   public void setAge(Integer age) { this.age = age; }

   @Override
   public String toString() {
      return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
   }
}

來看看ORM是怎么工作的吧:

/**
 * 解析類型注解
 */
private static String getColumnType(ColumnType columntype) {
   String type = "";
   switch (columntype.value()) {
      case CHAR:
         type += "CHAR";
         break;
      case STRING:
         type += "VARCHAR";
         break;
      case BOOLEAN:
         type += "BIT";
         break;
      case INTEGER:
         type += "INT";
         break;
      case LONG:
         type += "BIGINT";
         break;
      case FLOAT:
         type += "FLOAT";
         break;
      case DOUBLE:
         type += "DOUBLE";
         break;
      case DATETIME:
         type += "DATETIME";
         break;
      default:
         type += "VARCHAR";
         break;
   }
   return type;
}
/**
 * 解析信息注解
 */
private static String getExtraInfo(ExtraInfo extrainfo) {
   String info = "";
   if (null != extrainfo.name()) {
      info = extrainfo.name();
   } else {
      return null;
   }
   if (0 < extrainfo.length()) {
      info += " (" + extrainfo.length() + ")";
   } else {
      return null;
   }
   return info;
}
/**
 * 解析約束注解
 */
private static String getConstraints(Constraints con) {
   String constraints = "";
   if (con.primaryKey()) {
      constraints += " PRIMARY KEY";
   }
   if (!con.allowNull()) {
      constraints += " NOT NULL";
   }
   if (con.unique()) {
      constraints += " UNIQUE";
   }

   return constraints;
}

做了那么多的鋪墊,終于到了臨門一腳了,實(shí)現(xiàn)一個(gè)縫合怪了:

/**
 * 臨門一腳:實(shí)現(xiàn)一個(gè)縫合怪
 */
private static void createTable(List<String> list) {
   for (String className : list) {
      Class<?> clazz;
      try {
         clazz = Class.forName(className);
         DBTable dbTable = clazz.getAnnotation(DBTable.class);
         if (dbTable == null) {// 無DBTable注解
            continue;
         }
         // 轉(zhuǎn)大寫
         String tableName = clazz.getSimpleName().toUpperCase();
         StringBuilder sql = new StringBuilder("CREATE TABLE " + tableName + "(");
         for (Field field : clazz.getDeclaredFields()) {
            // 反射得到注解
            Annotation[] anns = field.getDeclaredAnnotations();
            if (anns.length < 1) {
               continue;
            }
            String columnInfo = "";
            // 類型判斷
            if (anns[0] instanceof TableColumn) {
               TableColumn column = (TableColumn) anns[0];
               String type = getColumnType(column.columntype());
               columnInfo = getExtraInfo(column.extrainfo());
               // 代替(
               columnInfo = columnInfo.replace("(", type + "(");
               columnInfo += getConstraints(column.constraints());
            }
            sql.append("\n " + columnInfo + ",");
         }
         // 刪除尾部的逗號(hào)
         String tableCreate = sql.substring(0, sql.length() - 1) + "\n);";
         System.out.println(tableCreate);
      } catch (ClassNotFoundException e) {
         e.printStackTrace();
      }
   }
}

驗(yàn)證效果的時(shí)候到了:

public static void main(String[] args) {
   Class<?> clazz = User.class;
   List<String> list = new ArrayList<>();
   list.add(clazz.getName());

   createTable(list);
}

當(dāng)然,實(shí)際的運(yùn)營(yíng)于生產(chǎn)環(huán)境中的ORM框架可要比這個(gè)小玩意復(fù)雜多了。但千變?nèi)f變,原理不變,ORM的核心——反射+ 注解——就是這么玩的。

到此這篇關(guān)于Java注解實(shí)現(xiàn)自己的ORM的文章就介紹到這了,更多相關(guān)Java注解ORM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 與web服務(wù)器鏈接的實(shí)例

    java 與web服務(wù)器鏈接的實(shí)例

    這篇文章主要介紹了java 與web服務(wù)器鏈接的實(shí)例的相關(guān)資料,使用net.Socket類sock.getInetAddress()方法獲得與Web服務(wù)器連接,需要的朋友可以參考下
    2017-07-07
  • java中ThreadLocal的應(yīng)用場(chǎng)景實(shí)例分析

    java中ThreadLocal的應(yīng)用場(chǎng)景實(shí)例分析

    在本篇文章里小編給大家整理的是一篇關(guān)于java中ThreadLocal的應(yīng)用場(chǎng)景實(shí)例分析,對(duì)此有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-02-02
  • 關(guān)于Java中你所不知道的Integer詳解

    關(guān)于Java中你所不知道的Integer詳解

    這篇文章主要給大家介紹了關(guān)于Java中你所不知道的一些關(guān)于Integer的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • 詳解如何使用MyBatis簡(jiǎn)化JDBC開發(fā)

    詳解如何使用MyBatis簡(jiǎn)化JDBC開發(fā)

    JavaEE?企業(yè)級(jí)?Java?項(xiàng)目中的經(jīng)典三層架構(gòu)為表現(xiàn)層,業(yè)務(wù)層和持久層.MyBatis?對(duì)?JDBC?代碼進(jìn)行了封裝,作為一款優(yōu)秀的持久層框架,專門用于簡(jiǎn)化JDBC開發(fā).本文主要介紹一下如何使用MyBatis簡(jiǎn)化JDBC開發(fā),需要的可以參考一下
    2023-01-01
  • Java將網(wǎng)絡(luò)圖片轉(zhuǎn)成輸入流以及將url轉(zhuǎn)成InputStream問題

    Java將網(wǎng)絡(luò)圖片轉(zhuǎn)成輸入流以及將url轉(zhuǎn)成InputStream問題

    這篇文章主要介紹了Java將網(wǎng)絡(luò)圖片轉(zhuǎn)成輸入流以及將url轉(zhuǎn)成InputStream問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • IDEA生成patch和使用patch的方法實(shí)現(xiàn)

    IDEA生成patch和使用patch的方法實(shí)現(xiàn)

    比如你本地修復(fù)的 bug,需要把增量文件發(fā)給客戶,很多場(chǎng)景下大家都需要手工整理修改的文件,并整理好目錄,這個(gè)很麻煩,那有沒有簡(jiǎn)單的技巧呢?本文主要介紹了IDEA生成patch和使用patch的方法實(shí)現(xiàn),感興趣的可以了解一下
    2023-08-08
  • java中Timer定時(shí)器的使用和啟動(dòng)方式

    java中Timer定時(shí)器的使用和啟動(dòng)方式

    這篇文章主要介紹了java中Timer定時(shí)器的使用和啟動(dòng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java操作ElasticSearch聚合查詢的示例代碼

    java操作ElasticSearch聚合查詢的示例代碼

    這篇文章主要介紹了java操作ElasticSearch聚合查詢的示例代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2024-08-08
  • 使用Java編寫一個(gè)好用的解析配置工具類

    使用Java編寫一個(gè)好用的解析配置工具類

    這篇文章主要為大家詳細(xì)介紹了如何使用Java編寫一個(gè)好用的解析配置工具類,支持解析格式有properties,yaml和yml,感興趣的可以了解下
    2024-11-11
  • 深入探究Java?@MapperScan實(shí)現(xiàn)原理

    深入探究Java?@MapperScan實(shí)現(xiàn)原理

    之前是直接在Mapper類上面添加注解@Mapper,這種方式要求每一個(gè)mapper類都需要添加此注解,麻煩。通過使用@MapperScan可以指定要掃描的Mapper類的包的路徑,這篇文章深入探究Java?@MapperScan的實(shí)現(xiàn)原理
    2023-01-01

最新評(píng)論

湘潭市| 清苑县| 咸宁市| 黔东| 临海市| 邛崃市| 军事| 玉树县| 浑源县| 南汇区| 兴仁县| 奈曼旗| 厦门市| 内黄县| 泸州市| 宣城市| 当阳市| 蕉岭县| 钟祥市| 井研县| 临湘市| 东阿县| 蓬安县| 武乡县| 天津市| 吴忠市| 驻马店市| 龙岩市| 漳浦县| 凤城市| 南召县| 海盐县| 会宁县| 广汉市| 肥乡县| 宜州市| 海安县| 巧家县| 舞钢市| 普定县| 漠河县|