国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2)

這篇具有很好參考價值的文章主要介紹了根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

目錄

一、數(shù)據(jù)庫設(shè)計

1.1、數(shù)據(jù)庫選擇

1.2、環(huán)境配置

1.3、建庫建表接口實(shí)現(xiàn)

1.4、封裝數(shù)據(jù)庫操作

1.5、針對 DataBaseManager 進(jìn)行單元測試

1.6、心得


一、數(shù)據(jù)庫設(shè)計


1.1、數(shù)據(jù)庫選擇

MySQL 是我們最熟悉的數(shù)據(jù)庫,但是這里我們選擇使用 SQLite,原因如下:

  1. SQLite 比 MySQL 更輕量:一個完整的 SQLite 數(shù)據(jù)庫,只有一個單獨(dú)的可執(zhí)行文件(不到 1M).
  2. SQLite 操作簡便:SQLite 只是一個本地數(shù)據(jù)庫,相當(dāng)于是直接操作本地的硬盤.
  3. SQLite 應(yīng)用也非常廣泛:在一些性能不高的設(shè)備上,SQLite 是數(shù)據(jù)庫的首選,尤其是移動端和嵌入式設(shè)備(Android 系統(tǒng)就是內(nèi)置的 SQLite).

1.2、環(huán)境配置

在 java?中直接使用 maven 把 SQLite 依賴引入即可(版本自行考慮)~

        <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <version>3.41.2.1</version>
        </dependency>

配置如下

spring:
  datasource:
    url: jdbc:sqlite:./data/meta.db
    username:
    password:
    driver-class-name: org.sqlite.JDBC

url:SQLite 的工作路徑,用來存儲數(shù)據(jù)在某個指定的文件中.

username & password:對于 SQLite 來說,不需要使用 用戶名密碼.? MySQL 是一個客戶端服務(wù)器結(jié)構(gòu)的程序,而 SQLite 則不是客戶端服務(wù)器結(jié)構(gòu)的程序,只有本地主機(jī)能訪問.

Ps:SQLite 雖然和 MySQL 不太一樣,但是都可以通過 MyBatis 這樣的框架來使用.

1.3、建庫建表接口實(shí)現(xiàn)

存儲的數(shù)據(jù)就是:交換機(jī)、隊(duì)列、綁定.

這里我們使用 MyBatis 來完成相關(guān)的 CRUD.

mapper 接口中提供三個建庫建表操作和針對這三個庫表進(jìn)行 CRUD 的操作.

@Mapper
public interface MetaMapper {

    //三個核心建表方法
    void createExchangeTable();
    void createQueueTable();
    void createBindingTable();

    //基于上述三個表,進(jìn)行 插入、刪除、查詢 操作
    void insertExchange(Exchange exchange);
    List<Exchange> selectAllExchange();
    void deleteExchange(String exchangeName);
    void insertQueue(MSGQueue queue);
    List<MSGQueue> selectAllQueue();
    void deleteQueue(String queueName);
    void insertBinding(Binding binding);
    List<Binding> selectAllBinding();
    void deleteBinding(Binding binding);


}

對應(yīng)的實(shí)現(xiàn)如下:

    <update id="createExchangeTable">
        create table if not exists exchange (
            name varchar(50) primary key,
            type int,
            durable boolean,
            autoDelete boolean,
            arguments varchar(1024)
        );
    </update>

    <update id="createQueueTable">
        create table if not exists queue (
            name varchar(50) primary key,
            durable boolean,
            exclusive boolean,
            autoDelete boolean,
            arguments varchar(1024)
        );
    </update>

    <update id="createBindingTable">
        create table if not exists binding (
            exchangeName varchar(50),
            queueName varchar(50),
            bindingKey varchar(256)
        )
    </update>

    <insert id="insertExchange" parameterType="com.example.rabbitmqproject.mqserver.core.Exchange">
        insert into exchange values (#{name}, #{type}, #{durable}, #{autoDelete}, #{arguments});
    </insert>

    <select id="selectAllExchange" resultType="com.example.rabbitmqproject.mqserver.core.Exchange">
        select * from exchange;
    </select>

    <delete id="deleteExchange" parameterType="com.example.rabbitmqproject.mqserver.core.Exchange">
        delete from exchange where name = #{name};
    </delete>

    <insert id="insertQueue" parameterType="com.example.rabbitmqproject.mqserver.core.MSGQueue">
        insert into queue values(#{name}, #{durable}, #{exclusive}, #{autoDelete}, #{arguments});
    </insert>

    <select id="selectAllQueue" resultType="com.example.rabbitmqproject.mqserver.core.MSGQueue">
        select * from queue;
    </select>

    <delete id="deleteQueue">
        delete from queue where name = #{name};
    </delete>

    <insert id="insertBinding">
        insert into binding values (#{exchangeName}, #{queueName}, #{bindingKey});
    </insert>

    <select id="selectAllBinding" resultType="com.example.rabbitmqproject.mqserver.core.Binding">
        select * from binding;
    </select>

    <delete id="deleteBinding">
        delete from binding where exchangeName = #{exchangeName} and queueName = #{queueName};
    </delete>

1.4、封裝數(shù)據(jù)庫操作

這里我們通過定制化 代碼 的方式來自動完成建庫建表的操作(符合?RabbitMQ 中間件的設(shè)定).

根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2),RabbitMQ,數(shù)據(jù)庫,sqlite,mybatis,rabbitmq

創(chuàng)建 DataBaseManager 類,來完成數(shù)據(jù)庫相關(guān)的操作,注意細(xì)節(jié)如下:

  1. 初始化方法:一般談到初始化,都會用到 構(gòu)造方法,但是這里我們使用一個 普通的方法 —— init();構(gòu)造方法一般是用來初始化類的屬性,不會涉及到太多的業(yè)務(wù)邏輯,而此處的初始化,帶有業(yè)務(wù)邏輯,還是單獨(dú)領(lǐng)出來,手動來調(diào)用比較合適.
  2. 建庫建表邏輯:這里期望,broker server 啟動的時候做出如下邏輯判斷:
    1. 如果數(shù)據(jù)庫已經(jīng)存在(表存在),不做任何操作.
    2. 如果數(shù)據(jù)庫不存在,則建庫建表,構(gòu)造默認(rèn)數(shù)據(jù).

Ps:怎么判定數(shù)據(jù)庫存在或者不存在?就判定 meta.db 文件是否存在即可(配置文件中的 url).

public class DataBaseManager {

    //這里不使用 Autowired 注解獲取,因?yàn)楫?dāng)前這個類需要我們后面手動管理
    private MetaMapper metaMapper;

    //針對數(shù)據(jù)庫進(jìn)行初始化
    public void init() {
        //手動獲取到 MetaMapper
        metaMapper = RabbitmqProjectApplication.context.getBean(MetaMapper.class);

        if(!checkDBExists()) {
            //數(shù)據(jù)庫不存在,就進(jìn)行建庫建表操作
            //先創(chuàng)建出目錄結(jié)構(gòu)(否則會報錯:找不到目錄結(jié)構(gòu))
            File dataDir = new File("./data");
            dataDir.mkdirs();
            //創(chuàng)建數(shù)據(jù)庫
            createTable();
            //插入默認(rèn)數(shù)據(jù)
            createDefaultData();
            System.out.println("[DataBaseManager] 數(shù)據(jù)庫初始化完成!");
        } else {
            //數(shù)據(jù)庫存在,什么都不做即可
            System.out.println("[DataBaseManager] 數(shù)據(jù)庫已存在!");
        }

    }


    private boolean checkDBExists() {
        File file = new File("./data/meta.db");
        return file.exists();
    }

    private void createTable() {
        metaMapper.createExchangeTable();
        metaMapper.createQueueTable();
        metaMapper.createBindingTable();
        System.out.println("[DataBaseManager] 創(chuàng)建表完成!");
    }

    /**
     * 添加默認(rèn)交換機(jī)
     * RabbitMQ 有一個這樣的設(shè)定:帶有一個 匿名 的交換機(jī),類型是 Direct
     */
    private void createDefaultData() {
        Exchange exchange = new Exchange();
        exchange.setName("");
        exchange.setType(ExchangeType.DIRECT);
        exchange.setDurable(true);
        exchange.setAutoDelete(false);
        metaMapper.insertExchange(exchange);
        System.out.println("[DataBaseManager] 創(chuàng)建初始數(shù)據(jù)完成!");
    }

    //把數(shù)據(jù)庫中其他操作也在這里封裝一下
    public void insertExchange(Exchange exchange) {
        metaMapper.insertExchange(exchange);
    }

    public List<Exchange> selectAllExchange() {
        return metaMapper.selectAllExchange();
    }

    public void deleteExchange(String exchangeName) {
        metaMapper.deleteExchange(exchangeName);
    }

    public void insertQueue(MSGQueue queue) {
        metaMapper.insertQueue(queue);
    }

    public List<MSGQueue> selectAllQueue() {
        return metaMapper.selectAllQueue();
    }

    public void deleteQueue(String queueName) {
        metaMapper.deleteQueue(queueName);
    }

    public void insertBinding(Binding binding) {
        metaMapper.insertBinding(binding);
    }

    public List<Binding> selectAllBinding() {
        return metaMapper.selectAllBinding();
    }

    public void deleteBinding(Binding binding) {
       metaMapper.deleteBinding(binding);
    }

    public void deleteDB() {
        //刪除文件
        File file = new File("./data/meta.db");
        boolean res = file.delete();
        if(res) {
            System.out.println("[DataBaseManager] 數(shù)據(jù)庫文件刪除完畢!");
        } else {
            System.out.println("[DataBaseManager] 數(shù)據(jù)庫文件刪除失敗!");
        }
        //刪除目錄
        File dataDir = new File("./data");
        boolean ret = dataDir.delete();
        if(ret) {
            System.out.println("[DataBaseManager] 數(shù)據(jù)庫目錄刪除完成!");
        } else {
            System.out.println("[DataBaseManager] 數(shù)據(jù)庫目錄刪除失敗!");
        }
    }

}

1.5、針對 DataBaseManager 進(jìn)行單元測試

設(shè)計單元測試,這里的要求就是單元測試用例和用例之間是需要相互獨(dú)立的,不會干擾,例如以下情況:

測試過程中,向數(shù)據(jù)庫中插入數(shù)據(jù) a .

在針對 b 進(jìn)行測試,可能 a 這里的數(shù)據(jù)會對 b 造成干擾.

Ps:這里不一定是數(shù)據(jù)庫,也可能是其他方面,例如是否搞了一個文件,是否占用了端口...

@SpringBootTest
public class DataBaseManagerTests {

    private DataBaseManager dataBaseManager = new DataBaseManager();

    @BeforeEach
    public void setUp() {
        RabbitmqProjectApplication.context = SpringApplication.run(RabbitmqProjectApplication.class);
        dataBaseManager.init();
    }

    @AfterEach
    public void setclose() {
        //此處不能直接刪除 數(shù)據(jù)庫文件 ,需要先關(guān)閉 context 對象
        //此處 context 對象持有了 MetaMapper 的實(shí)例, MetaMapper 又打開了 meta.db 數(shù)據(jù)庫
        //如果 meta.db 被別人打開了,此時刪除文件是不會成功的(Windows 系統(tǒng)限制, Linux 則不會)
        //另一方面 context 會占用 8080 端口,此處的 close 也是釋放 8080 端口
        RabbitmqProjectApplication.context.close();
        dataBaseManager.deleteDB();
    }

    @Test
    public void testInitTable() {
        List<Exchange> exchanges = dataBaseManager.selectAllExchange();
        List<MSGQueue> msgQueues = dataBaseManager.selectAllQueue();
        List<Binding> bindings = dataBaseManager.selectAllBinding();

        Assertions.assertEquals(1, exchanges.size());
        Assertions.assertEquals("", exchanges.get(0).getName());
        Assertions.assertEquals(ExchangeType.DIRECT, exchanges.get(0).getType());
        Assertions.assertEquals(0, msgQueues.size());
        Assertions.assertEquals(0, bindings.size());
    }

    private Exchange createTestExchange(String exchangeName) {
        Exchange  exchange = new Exchange();
        exchange.setName(exchangeName);
        exchange.setType(ExchangeType.FANOUT);
        exchange.setDurable(true);
        exchange.setAutoDelete(false);
        exchange.setArguments("aaa", 1);
        exchange.setArguments("bbb", 2);
        return exchange;
    }

    @Test
    public void insertExhangeTest() {
        Exchange exchange = createTestExchange("testExchange");
        dataBaseManager.insertExchange(exchange);
        List<Exchange> exchanges = dataBaseManager.selectAllExchange();
        Assertions.assertEquals(2, exchanges.size());
        Exchange testExchange = exchanges.get(1);
        Assertions.assertEquals("testExchange", testExchange.getName());
        Assertions.assertEquals(ExchangeType.FANOUT, testExchange.getType());
        Assertions.assertEquals(true, testExchange.isDurable());
        Assertions.assertEquals(false, testExchange.isAutoDelete());
        Assertions.assertEquals(1, testExchange.getArguments("aaa"));
        Assertions.assertEquals(2, testExchange.getArguments("bbb"));

    }

    @Test
    public void deleteExchangeTest() {
        Exchange exchange = createTestExchange("testExchange");
        dataBaseManager.insertExchange(exchange);
        List<Exchange> exchanges = dataBaseManager.selectAllExchange();
        Assertions.assertEquals(2, exchanges.size());
        Assertions.assertEquals("testExchange", exchanges.get(1).getName());

        //刪除
        dataBaseManager.deleteExchange("testExchange");
        exchanges = dataBaseManager.selectAllExchange();
        Assertions.assertEquals(1, exchanges.size());
    }

    private MSGQueue createTestQueue(String queueName) {
        MSGQueue queue = new MSGQueue();
        queue.setName(queueName);
        queue.setDurable(true);
        queue.setExclusive(false);
        queue.setAutoDelete(false);
        queue.setArguments("aaa", 1);
        queue.setArguments("bbb", 2);
        return queue;
    }

    @Test
    public void testInsertQueue() {
        MSGQueue queue = createTestQueue("testQueue");
        dataBaseManager.insertQueue(queue);
        List<MSGQueue> queues = dataBaseManager.selectAllQueue();
        Assertions.assertEquals(1, queues.size());
        MSGQueue msgQueue = queues.get(0);
        Assertions.assertEquals("testQueue", msgQueue.getName());
        Assertions.assertEquals(true, msgQueue.isDurable());
        Assertions.assertEquals(false, msgQueue.isExclusive());
        Assertions.assertEquals(false, msgQueue.isAutoDelete());
        Assertions.assertEquals(1, msgQueue.getArguments("aaa"));
        Assertions.assertEquals(2, msgQueue.getArguments("bbb"));
    }

    @Test
    public void testDeleteQueue() {
        MSGQueue queue = createTestQueue("testQueue");
        dataBaseManager.insertQueue(queue);
        List<MSGQueue> queues = dataBaseManager.selectAllQueue();
        Assertions.assertEquals(1, queues.size());

        //刪除
        dataBaseManager.deleteQueue("testQueue");
        queues = dataBaseManager.selectAllQueue();
        Assertions.assertEquals(0, queues.size());
    }

    private Binding createTestBinding(String exchangeName, String queueName) {
        Binding binding = new Binding();
        binding.setExchangeName(exchangeName);
        binding.setQueueName(queueName);
        binding.setBindingKey("testBindingKey");
        return binding;
    }

    @Test
    public void testInsertAndDeleteBinding() {
        Binding binding = createTestBinding("testExchange", "testQueue");
        dataBaseManager.insertBinding(binding);
        List<Binding> bindingList = dataBaseManager.selectAllBinding();
        Assertions.assertEquals(1, bindingList.size());
        binding = bindingList.get(0);
        Assertions.assertEquals("testExchange", binding.getExchangeName());
        Assertions.assertEquals("testQueue", binding.getQueueName());
        Assertions.assertEquals("testBindingKey", binding.getBindingKey());

        //刪除
        dataBaseManager.deleteBinding(binding);
        bindingList = dataBaseManager.selectAllBinding();
        Assertions.assertEquals(0, bindingList.size());
    }



}

當(dāng)然,我只是做了簡單的設(shè)計測試用例,實(shí)際上站在更嚴(yán)謹(jǐn)?shù)慕嵌龋€需要設(shè)計更豐富的測試用例~

相比于 功能/業(yè)務(wù)代碼,測試用例代碼編寫起來雖然比較無聊,但是重要性是非常大的,這些操作會大大提高整個項(xiàng)目的開發(fā)效率.

Ps:單元測試,本來就是開發(fā)要搞的活,寫代碼不可能沒有 bug,進(jìn)行周密的測試,是應(yīng)對 bug 最有效的手段.

1.6、心得

做好單元測試真的很重要,在 XXXMapper.xml 中,我在標(biāo)簽中設(shè)定了參數(shù)?parameterType,如下?

根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2),RabbitMQ,數(shù)據(jù)庫,sqlite,mybatis,rabbitmq

一啟動項(xiàng)目就報錯(?'sqlSessionFactory' 報錯),原因就是 Exchange 中缺少 getter 方法~~

但實(shí)際上我并“沒有缺少 getter 方法”,因?yàn)槲以賹懲陮傩砸院缶椭苯佑?IDEA 自動生成 getter/setter 方法了,但是!?。?我往數(shù)據(jù)庫中插入 arguments 時約定為 varchar 類型,因此 setter/getter 方法的無論在 set ,還是 get 時,得到都是 Map<String, Object> 類型,因此項(xiàng)目一啟動通過 MyBatis 加載 XXXMapper.xml 文件會直接報錯?。?!

根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2),RabbitMQ,數(shù)據(jù)庫,sqlite,mybatis,rabbitmq

正確的寫法因該是寫入/讀出數(shù)據(jù)庫,都因該序列化成 JSON 字符串的格式,如下:

根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2),RabbitMQ,數(shù)據(jù)庫,sqlite,mybatis,rabbitmq

?

根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2),RabbitMQ,數(shù)據(jù)庫,sqlite,mybatis,rabbitmq文章來源地址http://www.zghlxwxcb.cn/news/detail-646224.html

到了這里,關(guān)于根據(jù)源碼,模擬實(shí)現(xiàn) RabbitMQ - 通過 SQLite + MyBatis 設(shè)計數(shù)據(jù)庫(2)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包