国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

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

2019-11-14 14:57:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

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

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

下面是一個(gè)賬戶表的配置示例(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>

只定義了一個(gè)主鍵,有需要可對(duì)此擴(kuò)充。每列name對(duì)應(yīng)數(shù)據(jù)庫(kù)表的列名,field對(duì)應(yīng)邏輯對(duì)象的成員變量名,type對(duì)應(yīng)字段的類型,比如是int、string、timestamp等,有了名字和類型,就可以使用反射方式自動(dòng)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方式讀寫(xiě)的select、insert、update和delete的預(yù)處理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類的功能就這么多,下面是關(guān)鍵的Record類,其使用反射自動(dòng)存取數(shù)據(jù)。

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

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

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

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

    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)描述,通過(guò)反射獲取對(duì)應(yīng)字段的值然后設(shè)置。

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

toDBValue作用是將java邏輯類型轉(zhuǎn)成對(duì)應(yīng)數(shù)據(jù)庫(kù)類型,比如時(shí)間,在邏輯里是Long,而數(shù)據(jù)庫(kù)類型是Timestamp。

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

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

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

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

下面給出一個(gè)使用的完整示例:

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;    }

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

公共庫(kù)倉(cāng)庫(kù):JMetazion

服務(wù)器示例倉(cāng)庫(kù):JGameDemo

服務(wù)器架構(gòu)QQ交流群:330459037 Java游戲服務(wù)器架構(gòu)


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 沙湾县| 茌平县| 施甸县| 临武县| 曲麻莱县| 鄄城县| 安泽县| 湘潭市| 刚察县| 永年县| 中卫市| 剑阁县| 黔东| 和政县| 临泉县| 甘孜县| 新津县| 策勒县| 仙桃市| 江门市| 出国| 汶川县| 丰台区| 菏泽市| 班戈县| 巫溪县| 钟祥市| 策勒县| 定襄县| 上高县| 温宿县| 乾安县| 西畴县| 芒康县| 玉溪市| 侯马市| 东阳市| 延边| 鄂托克前旗| 锡林郭勒盟| 沙洋县|