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

Java游戲服務器之數(shù)據(jù)庫表存取封裝

 更新時間:2015年11月30日 15:11:18   作者:Metazion  
這篇文章主要介紹了Java游戲服務器之數(shù)據(jù)庫表存取封裝的相關資料,需要的朋友可以參考下

項目涉及的數(shù)據(jù)庫表并不多,但每個select、insert、update和delete都去手動拼接字符串,是很低效的,尤其在時常要修改結(jié)構(gòu)的情況下。開發(fā)的一個目標就是自動化,即能自動實現(xiàn)的事情就不要手動去做;還有一個原則是單一化,即盡量保證數(shù)據(jù)或邏輯一個入口一個出口。這個需求可以使用一些開源庫解決,但因為需求簡單,目標明確,沒有必要引入多余的第三方庫。于是自己寫了一個,至少滿足當前需求。

數(shù)據(jù)庫表的封裝,核心類有兩個,表(Table)和記錄(Record)。首先需要一個Table類保存數(shù)據(jù)庫表結(jié)構(gòu)的描述,并籍此自動生成相應SQL語句。其次需要一個Record類自動設置SQL參數(shù),并從返回結(jié)果集中自動生成邏輯對象。

table類表結(jié)構(gòu)描述可以有兩個來源,自動從數(shù)據(jù)庫獲取,或從配置表加載。這里選擇從配置表加載的方式,一來實現(xiàn)簡單,二來應用面更廣。

下面是一個賬戶表的配置示例(user.xml)。

<Table name="user" primaryKey="user_id" primaryField="userId">
  <Column name="username" field="username" type="2" />
  <Column name="password" field="password" type="2" />
  <Column name="salt" field="salt" type="1" />
  <Column name="reg_time" field="registerTime" type="3" />
  <Column name="last_login_time" field="lastLoginTime" type="3" />
</Table>

只定義了一個主鍵,有需要可對此擴充。每列name對應數(shù)據(jù)庫表的列名,field對應邏輯對象的成員變量名,type對應字段的類型,比如是int、string、timestamp等,有了名字和類型,就可以使用反射方式自動get和set數(shù)據(jù)。

Table類讀取配置文件獲得數(shù)據(jù)表的結(jié)構(gòu)描述。

public class Table<T> {
  public class TableField {
    public static final int TYPE_INTEGER = 1;
    public static final int TYPE_STRING = 2;
    public static final int TYPE_TIMESTAMP = 3;
    public String columnName = "";
    public String fieldName = "";
    public int type = 0;
  }
  private String tableName = "";
  private TableField primaryField = new TableField();
  private ArrayList<TableField> tableFields = new ArrayList<TableField>();
  private String selectAllSql = "";
  private String selectSql = "";
  private String insertSql = "";
  private String updateSql = "";
  private String deleteSql = "";
  ...

然后生成PrepareStatement方式讀寫的select、insert、update和delete的預處理SQL字符串。如update:

private String generateUpdateSql() {
    String sql = "UPDATE " + tableName + " SET ";
    int size = tableFields.size();
    for (int index = 0; index < size; ++index) {
      TableField tableField = tableFields.get(index);
      String conjunction = index == 0 ? "" : ",";
      String colSql = tableField.columnName + " = ?";
      sql = sql + conjunction + colSql;
    }

    sql = sql + " WHERE " + primaryField.columnName + "=?";
    return sql;
  }

Table類的功能就這么多,下面是關鍵的Record類,其使用反射自動存取數(shù)據(jù)。

public class Record<T> {
  private Table<T> table = null;
  private T object = null;
  ...

模板參數(shù)T即一個表記錄對應的邏輯對象。在我們的示例里,即賬戶數(shù)據(jù)類:

public class UserData implements Serializable {
  // 用戶ID
  public int userId = 0;
  // 用戶名
  public String username = "";
  // 密碼
  public String password = "";
  ...

有了SQL語句,要先設置參數(shù),才能執(zhí)行。主鍵和普通字段分開設置。

 public int setPrimaryParams(int start, PreparedStatement pst) throws Exception {
    Table<T>.TableField primaryField = table.getPrimaryField();
    Object value = getFieldValue(primaryField);
    value = toDBValue(primaryField, value);
    pst.setObject(start, value);
    return start + 1;
  }
  public int setNormalParams(int start, PreparedStatement pst) throws Exception {
    ArrayList<Table<T>.TableField> normalFields = table.getNoramlFields();
    final int size = normalFields.size();
    for (int index = 0; index < size; ++index) {
      Table<T>.TableField tableField = normalFields.get(index);
      Object value = getFieldValue(tableField);
      value = toDBValue(tableField, value);
      pst.setObject(start + index, value);
    }
    return start + size;
  }

就是根據(jù)表結(jié)構(gòu)描述,通過反射獲取對應字段的值然后設置。

 private Object getFieldValue(Table<T>.TableField tableField) throws Exception {
    Field field = object.getClass().getDeclaredField(tableField.fieldName);
    return field.get(object);
  }

toDBValue作用是將Java邏輯類型轉(zhuǎn)成對應數(shù)據(jù)庫類型,比如時間,在邏輯里是Long,而數(shù)據(jù)庫類型是Timestamp。

 private Object toDBValue(Table<T>.TableField tableField, Object value) {
    if (tableField.type == TableField.TYPE_TIMESTAMP) {
      value = new Timestamp((long) value);
    }
    return value;
  }

以設置update SQL參數(shù)為例:

 public void setUpdateParams(PreparedStatement pst) throws Exception {
    final int start = setNormalParams(1, pst);
    setPrimaryParams(start, pst);
  }

之后執(zhí)行該SQL語句就可以了。如果是select語句還會返回結(jié)果集(ResultSet),從結(jié)果集自動生成邏輯對象原理類似,算是一個逆過程,詳細參看文末代碼。

下面給出一個使用的完整示例:

private static final Table<UserData> udTable = new Table<UserData>();
...
udTable.load("user.xml");
...
public static boolean updateUserData(UserData userData) {
    boolean result = false;
    Record<UserData> record = udTable.createRecord();
    record.setObject(userData);
    PreparedStatement pst = null;
    try {
      String sql = udTable.getUpdateSql();
      pst = DbUtil.openConnection().prepareStatement(sql);
      record.setUpdateParams(pst);
      result = pst.executeUpdate() > 0;
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      DbUtil.closeConnection(null, pst);
    }
    return result;
  }

代碼封裝得很簡易,有更多需求可據(jù)此改進。

相關文章

  • java swing實現(xiàn)貪吃蛇雙人游戲

    java swing實現(xiàn)貪吃蛇雙人游戲

    這篇文章主要為大家詳細介紹了java swing實現(xiàn)貪吃蛇雙人小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • SpringBoot注解@Import原理之關于ConfigurationClassPostProcessor源碼解析

    SpringBoot注解@Import原理之關于ConfigurationClassPostProcessor源碼解析

    這篇文章主要介紹了SpringBoot注解@Import原理之關于ConfigurationClassPostProcessor源碼解析,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java 計算中位數(shù)的實現(xiàn)方法

    java 計算中位數(shù)的實現(xiàn)方法

    這篇文章主要介紹了java 計算中位數(shù)的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Java 中函數(shù) Function 的使用和定義示例小結(jié)

    Java 中函數(shù) Function 的使用和定義示例小結(jié)

    這篇文章主要介紹了Java 中函數(shù) Function 的使用和定義小結(jié),本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Java學習之Lambda表達式的使用詳解

    Java學習之Lambda表達式的使用詳解

    Lambda表達式是Java SE 8中一個重要的新特性,允許通過表達式來代替功能接口。本文將通過一些簡單的示例和大家講講Lamda表達式的使用,感興趣的可以了解一下
    2022-12-12
  • SpringBoot整合ES高級查詢方式

    SpringBoot整合ES高級查詢方式

    這篇文章主要介紹了SpringBoot整合ES高級查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • 詳解Java中的hashcode

    詳解Java中的hashcode

    這篇文章主要介紹了詳解Java中的hashcode,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • redis深入淺出分布式鎖實現(xiàn)上篇

    redis深入淺出分布式鎖實現(xiàn)上篇

    在單體應用中,如果我們對共享數(shù)據(jù)不進行加鎖操作,會出現(xiàn)數(shù)據(jù)一致性問題,我們的解決辦法通常是加鎖。下面我們一起聊聊使用redis來實現(xiàn)分布式鎖
    2022-08-08
  • SpringBoot獲取配置文件的簡單實現(xiàn)方法

    SpringBoot獲取配置文件的簡單實現(xiàn)方法

    這篇文章主要給大家介紹了關于SpringBoot如何獲取配置文件的簡單實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2020-05-05
  • Java中的EnumMap集合解析

    Java中的EnumMap集合解析

    這篇文章主要介紹了Java中的EnumMap集合解析,EnumMap是Map接口的一種實現(xiàn),專門用于枚舉類型的鍵,所有枚舉的鍵必須來自同一個枚舉,
    EnumMap不允許鍵為空,允許值為空,需要的朋友可以參考下
    2023-09-09

最新評論

台安县| 玉田县| 大足县| 美姑县| 平远县| 太谷县| 揭东县| 马边| 大英县| 仪征市| 三台县| 阿克陶县| 加查县| 沂南县| 林芝县| 盐边县| 邢台市| 大连市| 红安县| 商城县| 和田县| 清涧县| 东阳市| 泰兴市| 平阳县| 临澧县| 宕昌县| 浑源县| 河池市| 宝丰县| 根河市| 兰州市| 湘潭市| 方城县| 科尔| 揭阳市| 霞浦县| 长兴县| 名山县| 台南县| 靖江市|