成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

模仿hibernate框架,詳解hibernate部分方法設(shè)計(jì)

王陸寬 / 2883人閱讀

摘要:導(dǎo)讀源碼地址公司的持久層采用的框架,這也是很多公司使用的一種持久層框架。配置文件本項(xiàng)目以為開(kāi)發(fā)環(huán)境和以搭建的,分為包和包。一種是,這種是手動(dòng)提交事務(wù)。返回結(jié)果分為兩種,一種是以實(shí)體類直接返回,調(diào)用方法。

導(dǎo)讀

源碼地址

公司的持久層采用的hibernate框架,這也是很多公司使用的一種持久層框架。它將瞬時(shí)態(tài)的javabean對(duì)象轉(zhuǎn)化為持久態(tài)數(shù)據(jù)表的字段對(duì)象、或?qū)⒊志脩B(tài)的字段對(duì)象轉(zhuǎn)化為瞬時(shí)態(tài)javabean對(duì)象。我比較喜歡看源碼,看別人的架構(gòu)思想,因?yàn)?,筆者想向架構(gòu)師的方向進(jìn)發(fā)。看了別人的源碼,突然想模擬hibernate框架,自己寫(xiě)個(gè)框架出來(lái)。 這里去除了hibernate框架晦澀的地方,當(dāng)做自己學(xué)習(xí)材料還是不錯(cuò)的。里面涉及到反射、連接池等等。 這個(gè)項(xiàng)目中,你可以知道數(shù)據(jù)庫(kù)連接池是怎么建的,又是怎么回收的。 使用靜態(tài)代碼塊加載配置文件

以下詳細(xì)介紹我個(gè)人的項(xiàng)目,但肯定沒(méi)有人家源碼寫(xiě)得好,這里僅作為學(xué)習(xí)使用。

如果不懂的,可以私信我。

配置文件

本項(xiàng)目以idea為開(kāi)發(fā)環(huán)境和以maven搭建的,分為java包和test包。java包的配置文件放在resources下,代碼放在com.zby.simulationHibernate包下,如下是配置文件:

連接池

我們?cè)谑褂胔ibernate時(shí),一般會(huì)配置連接池,比如,初始化連接數(shù)是多少,最大連接數(shù)是多少?這個(gè)連接的是什么?我們?cè)趩?dòng)項(xiàng)目時(shí),hibernate根據(jù)初始的連接數(shù),來(lái)創(chuàng)建多少個(gè)數(shù)據(jù)庫(kù)連接對(duì)象,也就是jdbc中的Connection對(duì)象。

為什么要有這個(gè)連接池?因?yàn)椋看伍_(kāi)啟一個(gè)連接和關(guān)閉一個(gè)連接都是消耗資源的,我們開(kāi)啟了這些連接對(duì)象之后,把它們放在一個(gè)容器中,我們何時(shí)需要何時(shí)從容器中取出來(lái)。當(dāng)不需要的時(shí)候,再將踏進(jìn)放回到容器中。因而,可以減少占用的資源。

如下,是初始化的連接對(duì)象:

package com.zby.simulationHibernate.util.factory;

import com.zby.simulationHibernate.util.exception.GenericException;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Created By zby on 21:23 2019/1/23
 * 數(shù)據(jù)庫(kù)的連接
 */
public class Connect {

    /**
     * 連接池的初始值
     */
    private static int initPoolSize = 20;

    /**
     * 創(chuàng)建property的配置文件
     */
    protected static Properties properties;

    /**
     * 連接池的最小值
     */
    protected static int minPoolSize;


    /**
     * 連接池的最大值
     */
    protected static int maxPoolSize;

    //【2】靜態(tài)代碼塊
    static {
        //加載配置文件
        properties = new Properties();
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("db.properties");
        try {
            properties.load(is);
            minPoolSize = Integer.valueOf(properties.getProperty("jdbc.minConnPool"));
            if (minPoolSize <= initPoolSize)
                minPoolSize = initPoolSize;
            maxPoolSize = Integer.valueOf(properties.getProperty("jdbc.maxConnPool"));
            if (minPoolSize > maxPoolSize)
                throw new GenericException("連接池的最小連接數(shù)不能大于最大連接數(shù)");
        } catch (IOException e) {
            System.out.println("未找到配置文件");
            e.printStackTrace();
        }
    }

    /**
     * Created By zby on 16:50 2019/1/23
     * 獲取數(shù)據(jù)連接
     */
    protected java.sql.Connection createConnect() {
        String driverName = properties.getProperty("jdbc.driver");
        if (StringUtils.isEmpty(driverName)) {
            driverName = "com.mysql.jdbc.Driver";
        }
        String userName = properties.getProperty("jdbc.username");
        String password = properties.getProperty("jdbc.password");
        String dbUrl = properties.getProperty("jdbc.url");

        try {
            Class.forName(driverName);
            return DriverManager.getConnection(dbUrl, userName, password);
        } catch (ClassNotFoundException e) {
            System.out.println("找不到驅(qū)動(dòng)類");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("加載異常");
            e.printStackTrace();
        }
        return null;
    }
}
創(chuàng)建Session會(huì)話

我們?cè)谑褂胔ibernate時(shí),不是直接使用連接對(duì)象,而是,以會(huì)話的方式創(chuàng)建一個(gè)連接。創(chuàng)建會(huì)話的方式有兩種。一種是openSession,這種是手動(dòng)提交事務(wù)。getCurrentSession是自動(dòng)提交事務(wù)。

如代碼所示:

package com.zby.simulationHibernate.util.factory;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created By zby on 15:43 2019/1/23
 */
public class SqlSessionFactory implements SessionFactory {

    /**
     * 連接池
     */
    private static List connections;

    /**
     * 連接對(duì)象
     *
     * @return
     */
    private static Connect connect = new Connect();

    protected static List getConnections() {
        return connections;
    }


    //靜態(tài)代碼塊,初始化常量池
    static {
        connections = new ArrayList<>();
        Connection connection;
        for (int i = 0; i < Connect.minPoolSize; i++) {
            connection = connect.createConnect();
            connections.add(connection);
        }
    }

    @Override
    public Session openSession() {
        return getSession(false);
    }

    @Override
    public Session getCurrentSession() {
        return getSession(true);
    }

    /**
     * 獲取session
     *
     * @param autoCommit 是否自動(dòng)提交事務(wù)
     * @return
     */
    private Session getSession(boolean autoCommit) {
        //【1】判斷連接池有可用的連接對(duì)象
        boolean hasNoValidConn = hasValidConnction();
        //【2】沒(méi)有可用的連接池,使用最大的連接池
        if (!hasNoValidConn) {
            for (int i = 0; i < (Connect.maxPoolSize - Connect.minPoolSize); i++) {
                connections.add(connect.createConnect());
            }
        }
        //【3】有可用的連接
        for (Iterator iterator = connections.iterator(); iterator.hasNext(); ) {
            Connection connection = null;
            try {
                connection = (Connection) iterator.next();
                connection.setAutoCommit(autoCommit);
                Session session = new Session(connection);
                iterator.remove();
                return session;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * Created By zby on 21:50 2019/1/23
     * 當(dāng)我們沒(méi)開(kāi)啟一個(gè)連接,連接池的數(shù)目減少1,直到連接池的數(shù)量為0
     */
    private boolean hasValidConnction() {
        return null != connections && connections.size() != 0;
    }
}
數(shù)據(jù)查找

我們既然使用這個(gè)框架,必然要有數(shù)據(jù)查找的功能。返回結(jié)果分為兩種,一種是以實(shí)體類直接返回,調(diào)用addEntity方法。但是,多數(shù)情況下,是多張表聯(lián)合查詢的結(jié)果,這種情況下,直接以實(shí)體類接肯定不可以的。因而,我們需要自定義接收對(duì)象,并將查找結(jié)果進(jìn)行過(guò)濾,再封裝成我們想要的對(duì)象。

第一種,以實(shí)體類返回

/**
 * Created By zby on 23:19 2019/1/23
 * 體檢反射的實(shí)體類
 */
public SqlQuery addEntity(Class persistenceClass) {
    this.persistenceClass = persistenceClass;
    return this;
}

第二種,過(guò)濾后返回?cái)?shù)據(jù)

 /**
 * Created By zby on 19:18 2019/1/27
 * 創(chuàng)建類型
 */
public SqlQuery addScalar(String tuple, String alias) {
    if (CommonUtil.isNull(aliasMap)) {
        aliasMap = new HashMap<>();
    }
    for (Map.Entry entry : aliasMap.entrySet()) {
        String key = entry.getKey();
        if (key.equals(tuple))
            throw new GenericException("alias已經(jīng)存在,即alias=" + key);
        String value = aliasMap.get(key);
        if (value.equals(alias) && key.equals(tuple))
            throw new GenericException("當(dāng)前alias的type已經(jīng)存在,alias=" + key + ",type=" + value);
    }
    aliasMap.put(tuple, alias);
    return this;
}

/**
 * Created By zby on 9:20 2019/1/28
 * 數(shù)據(jù)轉(zhuǎn)換問(wèn)題
 */
public SqlQuery setTransformer(ResultTransformer transformer) {
    if (CommonUtil.isNull(aliasMap)) {
        throw new IllegalArgumentException("請(qǐng)?zhí)砑愚D(zhuǎn)換的屬性數(shù)量");
    }
    transformer.transformTuple(aliasMap);
    this.transformer = transformer;
    return this;
}

以集合的方式返回?cái)?shù)據(jù):

/**
 * Created By zby on 17:02 2019/1/29
 * 設(shè)置查找參數(shù)
 */
public SqlQuery setParamter(int start, Object param) {
    if (CommonUtil.isNull(columnParamer))
        columnParamer = new HashMap<>();
    columnParamer.put(start, param);
    return this;
}

/**
 * Created By zby on 16:41 2019/1/24
 * 查找值
 */
public List list() {
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    try {
        statement = connection.prepareStatement(sql);
        if (CommonUtil.isNotNull(columnParamer)) {
            for (Map.Entry entry : columnParamer.entrySet()) {
                int key = entry.getKey();
                Object value = entry.getValue();
                statement.setObject(key + 1, value);
            }
        }
        resultSet = statement.executeQuery();
        PersistentObject persistentObject = new PersistentObject(persistenceClass, resultSet);
        if (CommonUtil.isNotNull(aliasMap))
            return persistentObject.getPersist(transformer);
        return persistentObject.getPersist();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        SessionClose.closeConnStateResSet(connection, statement, resultSet);
    }
    return null;
}

返回唯一值

/**
 * Created By zby on 16:41 2019/1/24
 * 查找值
 */
public T uniqueResult() {
    List list = list();
    if (CommonUtil.isNull(list))
        return null;
    if (list.size() > 1)
        throw new GenericException("本來(lái)需要返回一個(gè)對(duì)象,卻返回 " + list.size() + "個(gè)對(duì)象");
    return list.get(0);
}

測(cè)試

 @Test
    public void testList() {
        Session session = new SqlSessionFactory().openSession();
        String sql = "SELECT " +
                " customer_name AS customerName, " +
                "  `name` AS projectName " +
                "FROM " +
                " project where id >= ? and id <= ?";
        SqlQuery query = session.createSqlQuery(sql);
        query.setParamter(0, 1);
        query.setParamter(1, 2);
        query.addScalar("customerName", StandardBasicTypes.STRING)
                .addScalar("projectName", StandardBasicTypes.STRING);
        query.setTransformer(Transforms.aliasToBean(ProjectData.class));
        List projects = query.list();
        for (ProjectData project : projects) {
            System.out.println(project.getCustomerName() + " " + project.getProjectName());
        }
    }

    @Ignore
    public void testListNoData() {
        Session session = new SqlSessionFactory().openSession();
        String sql = "SELECT " +
                " customer_name AS customerName, " +
                "  `name` AS projectName " +
                "FROM " +
                " project where id >= ? and id <= ?";
        SqlQuery query = session.createSqlQuery(sql).
                setParamter(0, 1).
                setParamter(1, 2).
                addEntity(Project.class);
        List projects = query.list();
        for (Project project : projects) {
            System.out.println(project.getCustomerName() + " " + project.getGuestCost());
        }
    }

保存數(shù)據(jù)

我們這里以 merge 方法來(lái)保存數(shù)據(jù),因?yàn)檫@個(gè)方法非常的特殊,我們?cè)谶@里做特殊說(shuō)明。如果該瞬時(shí)態(tài)的對(duì)象有主鍵,而且,其在數(shù)據(jù)表中已經(jīng)存在該主鍵的字段對(duì)象,我們此時(shí)就更新該數(shù)據(jù)表。如果數(shù)據(jù)表中沒(méi)有當(dāng)前主鍵的字段對(duì)象,我們向數(shù)據(jù)庫(kù)中添加該對(duì)象的值。如果該瞬時(shí)態(tài)的對(duì)象沒(méi)有主鍵,我們直接在數(shù)據(jù)表中添加該對(duì)象。

如代碼所示:

 /**
 * Created By zby on 15:41 2019/1/29
 * 合并,首先判斷id是否存在,若id存在則更新,若id不存在,則保存數(shù)據(jù)
 */
public T merge(T t) {
    if (CommonUtil.isNull(t))
        throw new IllegalArgumentException("參數(shù)為空");
    Class clazz = (Class) t.getClass();
    Field[] fields = clazz.getDeclaredFields();
    boolean isContainsId = CommonUtil.isNotNull(PropertyUtil.containId(fields)) ? true : false;
    long id = PropertyUtil.getIdValue(fields, t, propertyAccessor);
    if (isContainsId) {
        return id > 0L ? update(t) : save(t);
    }
    return save(t);
}

  /**
 * Created By zby on 17:37 2019/1/29
 * 保存數(shù)據(jù)
 */
public T save(T t) {
    if (CommonUtil.isNull(t))
        throw new RuntimeException("不能保存空對(duì)象");
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    StringBuilder columnJoint = new StringBuilder();
    StringBuilder columnValue = new StringBuilder();
    try {
        Field[] fields = t.getClass().getDeclaredFields();
        String sql = " insert into " + ClassUtil.getClassNameByGenericity(t) + "(";
        for (int i = 0; i < fields.length; i++) {
            String propertyName = fields[i].getName();
            Object propertyValue = propertyAccessor.getPropertyValue(t, propertyName);
            if (CommonUtil.isNotNull(propertyValue)) {
                String columnName = PropertyUtil.propertyNameTransformColumnName(propertyName, true);
                if (StandardBasicTypes.BOOLEAN.equalsIgnoreCase(fields[i].getGenericType().toString())) {
                    columnJoint.append("is_" + columnName + ",");
                    columnValue.append(propertyValue + ",");
                } else if (StandardBasicTypes.LONG.equalsIgnoreCase(fields[i].getGenericType().toString())
                        || StandardBasicTypes.FLOAT.equalsIgnoreCase(fields[i].getGenericType().toString())
                        || StandardBasicTypes.DOUBLE.equalsIgnoreCase(fields[i].getGenericType().toString())
                        || StandardBasicTypes.INTEGER.equalsIgnoreCase(fields[i].getGenericType().toString())) {
                    columnJoint.append(columnName + ",");
                    columnValue.append(propertyValue + ",");
                } else if (StandardBasicTypes.DATE.equalsIgnoreCase(fields[i].getGenericType().toString())) {
                    columnJoint.append(columnName + ",");
                    columnValue.append(""" + DateUtil.SIMPLE_DATE_FORMAT.format((Date) propertyValue) + "",");
                } else {
                    columnJoint.append(columnName + ",");
                    columnValue.append(""" + propertyValue + "",");
                }
            }
        }
        columnJoint = StringUtil.replace(columnJoint, ",");
        columnValue = StringUtil.replace(columnValue, ",");
        sql += columnJoint + ") VALUES(" + columnValue + ")";
        System.out.println(sql);
        statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
        statement.executeUpdate();
        resultSet = statement.getGeneratedKeys();
        while (resultSet.next()) {
            return load((Class) t.getClass(), resultSet.getLong(1));
        }
        return t;
    } catch (SQLException e) {
        System.out.println("保存數(shù)據(jù)出錯(cuò),實(shí)體對(duì)象為=" + t);
        e.printStackTrace();
    } finally {
        SessionClose.closeConnStateResSet(connection, statement, resultSet);
    }
    return null;
}

測(cè)試代碼:

 @Test
public void testSave() {
    Session session = new SqlSessionFactory().getCurrentSession();
    Project project = new Project();
    project.setCustomerName("hhhh");
    project.setCreateDatetime(new Date());
    project.setDeleted(true);
    project = (Project) session.save(project);
    System.out.println(project.getId());
}

通過(guò)id加載對(duì)象

有時(shí),我們只要根據(jù)當(dāng)前對(duì)象的id,獲取當(dāng)前對(duì)象的全部信息,因而,我們可以這樣寫(xiě):

 /**
 * Created By zby on 16:36 2019/1/29
 * 通過(guò)id獲取對(duì)象
 */
public T load(Class clazz, Long id) {
    if (CommonUtil.isNull(clazz))
        throw new IllegalArgumentException("參數(shù)為空");
    String className = ClassUtil.getClassNameByClass(clazz);
    String sql = " select * from " + className + " where id= ? ";
    SqlQuery query = createSqlQuery(sql)
            .setParamter(0, id)
            .addEntity(clazz);
    return (T) query.uniqueResult();
}

測(cè)試代碼:

@Test
public void testload() {
    Session session = new SqlSessionFactory().openSession();
    Project project = (Project) session.load(Project.class, 4L);
    System.out.println(project);
}

回收連接對(duì)象

當(dāng)我們使用完該連接對(duì)象后,需要將對(duì)象放回到容器中,并不是直接調(diào)用connection.close()方法,而是調(diào)用這個(gè)方法:

 /**
 * Created By zby on 16:10 2019/3/17
 * 獲取容器的對(duì)象,如果是關(guān)閉session,則將連接對(duì)象放回到容器中
 * 如果是開(kāi)啟session,則從容器中刪除該連接對(duì)象
 */
protected static List getConnections() {
    return connections;
}

 /**
 * Created By zby on 22:45 2019/1/23
 * 

* 當(dāng)關(guān)閉當(dāng)前會(huì)話時(shí),這并非真正的關(guān)閉會(huì)話 * 只是將連接對(duì)象放回到連接池中 */ public static void closeConn(Connection connection) { SqlSessionFactory.getConnections().add(connection); }

總結(jié)

寫(xiě)框架其實(shí)是不難的,難就難在如何設(shè)計(jì)框架?;蛘哒f(shuō),難就難在基礎(chǔ)不牢。如果基礎(chǔ)打不牢的話,很難往上攀升。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/73729.html

相關(guān)文章

  • Java 程序員必備的 15 個(gè)框架,前 3 個(gè)地位無(wú)可動(dòng)搖!

    摘要:官網(wǎng)源碼推薦從開(kāi)始手寫(xiě)一個(gè)框架更多請(qǐng)?jiān)诩夹g(shù)棧微信公眾號(hào)后臺(tái)回復(fù)關(guān)鍵字。是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)進(jìn)行了非常輕量級(jí)的對(duì)象封裝,它將與數(shù)據(jù)庫(kù)表建立映射關(guān)系,是一個(gè)全自動(dòng)的框架。 Java 程序員方向太多,且不說(shuō)移動(dòng)開(kāi)發(fā)、大數(shù)據(jù)、區(qū)塊鏈、人工智能這些,大部分 Java 程序員都是 Java Web/后端開(kāi)發(fā)。那作為一名 Java Web 開(kāi)發(fā)程序員必須需要熟悉哪些框架呢? 今天...

    galaxy_robot 評(píng)論0 收藏0
  • 納稅服務(wù)系統(tǒng)【總結(jié)】

    摘要:要是使用到日歷的話,我們想到使用這個(gè)日歷類上面僅僅是我個(gè)人總結(jié)的要點(diǎn),如果有錯(cuò)誤的地方還請(qǐng)大家給我指正。 納稅服務(wù)系統(tǒng)總結(jié) 納稅服務(wù)系統(tǒng)是我第一個(gè)做得比較大的項(xiàng)目(不同于javaWeb小項(xiàng)目),該項(xiàng)目系統(tǒng)來(lái)源于傳智Java32期,十天的視頻課程(想要視頻的同學(xué)關(guān)注我的公眾號(hào)就可以直接獲取了) 我跟著練習(xí)一步一步完成需求,才發(fā)覺(jué)原來(lái)Java是這樣用來(lái)做網(wǎng)站的,Java有那么多的類庫(kù),頁(yè)面...

    ispring 評(píng)論0 收藏0
  • Java 事務(wù)詳解

    摘要:一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。持久性也稱永久性,指一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就應(yīng)該是永久性的。事務(wù)與相關(guān)聯(lián),并通過(guò)調(diào)用實(shí)例化。強(qiáng)制此事務(wù)回滾。為此事務(wù)注冊(cè)用戶同步回調(diào)。檢查事務(wù)是否成功提交。 一、事務(wù) (1)事務(wù)(Transaction),一般是指要做的或所做的事情。在計(jì)算機(jī)術(shù)語(yǔ)中是指訪問(wèn)并可能更新數(shù)據(jù)庫(kù)中各種數(shù)據(jù)項(xiàng)的一個(gè)程序執(zhí)行單元(unit)。 (2)事務(wù)應(yīng)該具有...

    cyrils 評(píng)論0 收藏0
  • Hibernate配置及自定義注冊(cè)映射文件

    摘要:一配置屬性詳解可以在各式各樣不同環(huán)境下工作而設(shè)計(jì)的因此存在著大量的配置參數(shù)。以簡(jiǎn)便操作,多數(shù)配置參數(shù)都有默認(rèn)的配置值也是我們?nèi)粘J褂玫谋仨毱贰? Hibernate (開(kāi)放源代碼的對(duì)象關(guān)系映射框架) Hibernate是一個(gè)開(kāi)放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝, 它將POJO與數(shù)據(jù)庫(kù)表建立映射關(guān)系,是一個(gè)全自動(dòng)的orm框架,hibernat...

    coordinate35 評(píng)論0 收藏0
  • Java3y文章目錄導(dǎo)航

    摘要:前言由于寫(xiě)的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫(xiě)的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡(jiǎn)單 注解就這么簡(jiǎn)單 Druid數(shù)據(jù)庫(kù)連接池...

    KevinYan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<