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

SpringBoot中間件ORM框架實(shí)現(xiàn)案例詳解(Mybatis)

 更新時(shí)間:2023年07月26日 15:03:21   作者:看表該更新博客了  
這篇文章主要介紹了SpringBoot中間件ORM框架實(shí)現(xiàn)案例詳解(Mybatis),本篇文章提煉出mybatis最經(jīng)典、最精簡(jiǎn)、最核心的代碼設(shè)計(jì),來(lái)實(shí)現(xiàn)一個(gè)mini-mybatis,從而熟悉并掌握ORM框架的涉及實(shí)現(xiàn),需要的朋友可以參考下

源碼地址(已開源)https://gitee.com/sizhaohe/mini-mybatis.git 跟著源碼及下述UML圖來(lái)理解上手會(huì)更快,拒絕浮躁,沉下心來(lái)搞

定義:

ORM:Object Relational Mapping --> 對(duì)象關(guān)系映射,是一種程序設(shè)計(jì)技術(shù),用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z(yǔ)言里面不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換

需求背景:

記不記得剛開始學(xué)JAVA時(shí),編寫一大串JDBC相關(guān)代碼來(lái)進(jìn)行與數(shù)據(jù)庫(kù)的交互,日后我們接觸到的MyBatis、MyBatisPlus等都是使用ORM組件來(lái)實(shí)現(xiàn)的框架。

本篇文章提煉出mybatis【最】經(jīng)典、【最】精簡(jiǎn)、【最】核心的代碼設(shè)計(jì),來(lái)實(shí)現(xiàn)一個(gè)【mini-mybatis】,從而熟悉并掌握ORM框架的涉及實(shí)現(xiàn)。

方案設(shè)計(jì):

  • 中間的四部分處理是ORM框架的核心內(nèi)容
  • 這個(gè)框架會(huì)提供出SqlSession工廠以及調(diào)用方式

代碼展示

UML圖

很重要,建議code前跟我一樣,先將類UML圖整理出來(lái),整個(gè)類的依賴關(guān)系及代碼執(zhí)行流程會(huì)一目而然。

  • 以上為ORM框架實(shí)現(xiàn)核心類:加載mysql配置文件、對(duì)mapper-xml解析、獲取數(shù)據(jù)庫(kù)session、操作數(shù)據(jù)庫(kù)及封裝響應(yīng)結(jié)果。

實(shí)現(xiàn)細(xì)節(jié)

1.定義sqlsession接口

對(duì)數(shù)據(jù)庫(kù)的定義和處理,本篇我們只封裝一個(gè) T selectOne(Object param);

public interface SqlSession {
    <T> T selectOne(String statement, Object parameter);
    void close();
}

2.DefaultSqlSession(SqlSession的實(shí)現(xiàn))

使用rt.jar包下(java.lang.sql包下)

Connection接口(負(fù)責(zé)與數(shù)據(jù)庫(kù)進(jìn)行連接)及PreparedStatement(執(zhí)行具體sql)接口來(lái)實(shí)現(xiàn)

public class DefaultSqlSession implements SqlSession{
    private Connection connection;
    private Map<String,XNode> mapperElement;
    public DefaultSqlSession(Connection connection, Map<String, XNode> mapperElement) {
        this.connection = connection;
        this.mapperElement = mapperElement;
    }
    @Override
    public <T> T selectOne(String statement, Object parameter) {
        XNode xNode = mapperElement.get(statement);
        Map<Integer, String> parameterMap = xNode.getParameter();
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(xNode.getSql());
            buildParameter(preparedStatement, parameter, parameterMap);
            // SQL執(zhí)行結(jié)果集的行數(shù)據(jù)
            ResultSet resultSet = preparedStatement.executeQuery();
            List<T> objects = resultSet2Obj(resultSet, Class.forName(xNode.getResultType()));
            return objects.get(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    private <T> List<T> resultSet2Obj(ResultSet resultSet, Class<?> clazz) {
        List<T> list = new ArrayList<>();
        try {
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            // 每次遍歷行值
            while (resultSet.next()) {
                T obj = (T) clazz.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    Object value = resultSet.getObject(i);
                    String columnName = metaData.getColumnName(i);
                    String setMethod = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);
                    Method method;
                    if (value instanceof Timestamp) {
                        method = clazz.getMethod(setMethod, Date.class);
                    } else {
                        method = clazz.getMethod(setMethod, value.getClass());
                    }
                    method.invoke(obj, value);
                }
                list.add(obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
    @Override
    public void close() {
        if (null == connection) return;
        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    private void buildParameter(PreparedStatement preparedStatement, Object parameter, Map<Integer, String> parameterMap) throws SQLException, IllegalAccessException {
        int size = parameterMap.size();
        // 單個(gè)參數(shù)
        if (parameter instanceof Long) {
            for (int i = 1; i <= size; i++) {
                preparedStatement.setLong(i, Long.parseLong(parameter.toString()));
            }
            return;
        }else{
            // TODO 后面緊跟的章節(jié)繼續(xù)補(bǔ)充其他類型的入?yún)?
        }
    }
}

3.定義SqlSessionFactory接口

每次執(zhí)行一個(gè)SQL語(yǔ)句,應(yīng)用程序都需要獲取一個(gè)SqlSession對(duì)象。SqlSession對(duì)象是執(zhí)行持久化操作的入口點(diǎn),可以用于執(zhí)行SQL語(yǔ)句、刷新緩存、提交事務(wù)等操作。建議在使用完SqlSession后,及時(shí)關(guān)閉它來(lái)釋放資源。

public interface SqlSessionFactory {
    SqlSession openSession();
}

4.DefaultSqlSessionFactory(上述接口實(shí)現(xiàn)類)

構(gòu)造方法中向下傳遞了Configuration配置文件

public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration;
    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }
    @Override
    public SqlSession openSession() {
        return new DefaultSqlSession(configuration.getConnection(), configuration.getMapperElement());
    }
}

5.SqlSessionFactoryBuilder

數(shù)據(jù)庫(kù)操作的核心類,負(fù)責(zé)解析Mapper文件(拿datasource,數(shù)據(jù)庫(kù)連接信息,mapper文件中sql的各個(gè)信息如id,入返參類型,sql)

public class SqlSessionFactoryBuilder {
    public DefaultSqlSessionFactory build(Reader reader) {
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            document = saxReader.read(new InputSource(reader));
            // 拿到根標(biāo)簽元素
            Element rootElement = document.getRootElement();
            Configuration configuration = parseConfiguration(rootElement);
            return new DefaultSqlSessionFactory(configuration);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
    public Configuration parseConfiguration(Element rootElement) {
        Configuration configuration = new Configuration();
        configuration.setDataSource(dataSource(rootElement.selectNodes("http://dataSource")));
        configuration.setConnection(connection(configuration.getDataSource()));
        configuration.setMapperElement(mapperElement(rootElement.selectNodes("http://mappers")));
        return configuration;
    }
    private Map<String, String> dataSource(List<Element> list) {
        Map<String, String> dataSource = new HashMap<>(4);
        Element element = list.get(0);
        List content = element.content();
        for (Object o : content) {
            Element e = (Element) o;
            String name = e.attributeValue("name");
            String value = e.attributeValue("value");
            dataSource.put(name, value);
        }
        return dataSource;
    }
    private Connection connection(Map<String, String> dataSource) {
        try {
            return DriverManager.getConnection(dataSource.get("url"), dataSource.get("username"), dataSource.get("password"));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    private Map<String, XNode> mapperElement(List<Element> list) {
        Map<String, XNode> map = new HashMap<>();
        Element element = list.get(0);
        List content = element.content();
        try {
            for (Object o : content) {
                Element e = (Element) o;
                // 拿到mapper文件對(duì)應(yīng)地址
                String resource = e.attributeValue("resource");
                Reader reader = Resources.getResourceAsReader(resource);
                SAXReader saxReader = new SAXReader();
                Document document = saxReader.read(new InputSource(reader));
                Element rootElement = document.getRootElement();
                String namespace = rootElement.attributeValue("namespace");
                List<Element> selectNodes = rootElement.selectNodes("select");
                for (Element ele : selectNodes) {
                    String id = ele.attributeValue("id");
                    String parameterType = ele.attributeValue("parameterType");
                    String resultType = ele.attributeValue("resultType");
                    String sql = ele.getText();
                    // ? 匹配
                    Map<Integer, String> parameter = new HashMap<>();
                    Pattern pattern = Pattern.compile("(#\\{(.*?)})");
                    Matcher matcher = pattern.matcher(sql);
                    for (int i = 1; matcher.find(); i++) {
                        String g1 = matcher.group(1);
                        String g2 = matcher.group(2);
                        parameter.put(i, g2);
                        sql = sql.replace(g1, "?");
                    }
                    XNode xNode = new XNode();
                    xNode.setId(id);
                    xNode.setNameSpace(namespace);
                    xNode.setParameterType(parameterType);
                    xNode.setResultType(resultType);
                    xNode.setSql(sql);
                    xNode.setParameter(parameter);
                    map.put(namespace + "." + id, xNode);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }
}

測(cè)試驗(yàn)證

建表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL COMMENT '自增id',
  `userId` varchar(9) DEFAULT NULL COMMENT '用戶ID',
  `userNickName` varchar(32) DEFAULT NULL COMMENT '用戶昵稱',
  `userHead` varchar(255) DEFAULT NULL COMMENT '用戶頭像',
  `userPassword` varchar(255) DEFAULT NULL COMMENT '用戶密碼',
  `createTime` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
  `updateTime` datetime NOT NULL COMMENT '更新時(shí)間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES (1, '001', 'xxx', '001', '123', '2023-07-14 17:33:55', '2023-07-14 17:33:58');
INSERT INTO `user` VALUES (2, '002', 'xxx2', '002', '123', '2023-07-14 17:33:55', '2023-07-14 17:33:58');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;

定義POJO及DAO

@Data
public class User {
    private Long id;
    private String userId;          // 用戶ID
    private String userNickName;    // 昵稱
    private String userHead;        // 頭像
    private String userPassword;    // 密碼
    private Date createTime;        // 創(chuàng)建時(shí)間
    private Date updateTime;        // 更新時(shí)間
}
public interface IUserDao {
     User queryUserInfoById(Long id);
}

ORM配置文件--mybatis-config-datasource.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://172.17.1.245:3306/airticketbasedb?useUnicode=true"/>
                <property name="username" value="write"/>
                <property name="password" value="write123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/User_Mapper.xml"/>
    </mappers>
</configuration>

Mapper配置

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.minimybatis.dao.IUserDao">
    <select id="queryUserInfoById" parameterType="java.lang.Long" resultType="com.example.minimybatis.po.User">
        SELECT id, userId, userNickName, userHead, userPassword, createTime
        FROM user
        where id = #{id}
    </select>
</mapper>

測(cè)試類

public class ApiTest {
    @Test
    public void test(){
        String resouce = "mybatis-config-datasource.xml";
        Reader reader;
        try{
            reader = Resources.getResourceAsReader(resouce);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            User user = sqlSession.selectOne(
                    "com.example.minimybatis.dao.IUserDao.queryUserInfoById",
                    1L);
            System.out.println(JSONObject.toJSONString(user));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

總結(jié)

比mybatis小很多,取其(mybaits)精華來(lái)達(dá)到掌握ORM框架的目的

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

相關(guān)文章

最新評(píng)論

尚义县| 金堂县| 沿河| 苗栗县| 衡南县| 泸水县| 铁力市| 新闻| 兴海县| 丰县| 吉林省| 青阳县| 余姚市| 长宁区| 柯坪县| 汕尾市| 沂源县| 屯门区| 英德市| 兰西县| 武邑县| 喜德县| 洞头县| 淮滨县| 内丘县| 那坡县| 门源| 越西县| 安新县| 溧水县| 辰溪县| 页游| 芮城县| 辽源市| 方正县| 理塘县| 嵩明县| 瓮安县| 巴中市| 江达县| 贵阳市|