Message queue (3) - encapsulates the operation of the database

foreword

In the previous blog, we wrote some operations of building databases and tables about switches, queues, bindings, and writing to databases. Service calls, and after writing the class, test whether the code is complete

Implement encapsulation

After writing the above interface class and xml, we want to create a class to call various methods in the interface class and perform some operations on the database

Create the DataBaseManager class

In this class, we need to complete the operation of building a database and table, and encapsulate some methods of adding, deleting, checking and modifying the table (here, because the database we use is SQLite, which is a file, so when calling the operation of creating a table When the library is automatically built)
the method of implementation

  1. init() initialization, if there is no table in this method, create a table
  2. checkDB, check whether the database file exists
  3. createtable create table
  4. default creates a default switch to plug into
  5. delete delete database files
  6. The rest is to encapsulate the method of queue switch binding

The introduction of various methods is written into the code, you can read it by yourself

package com.example.demo.mqServer.dataCenter;

import com.example.demo.MqApplication;
import com.example.demo.mqServer.core.Binding;
import com.example.demo.mqServer.core.Exchange;
import com.example.demo.mqServer.core.ExchangeType;
import com.example.demo.mqServer.core.MSGQueue;
import com.example.demo.mqServer.mapper.MateMapper;

import java.io.File;
import java.util.List;

public class DataBaseManager {
    
    
    private MateMapper mateMapper;

    // 针对数据库进行初始化
    public void init() {
    
    
        // 手动获取matemapper 对象
        mateMapper = MqApplication.context.getBean(MateMapper.class);

        // 手动的获取到 MetaMapper
        if (!checkDBExists()) {
    
    
            //如果数据库不存在,就进行建表操作
            // 先创建一个data目录
            File dataDir = new File("./data");
            dataDir.mkdirs();
            createTable();
            // 插入默认数据
            createDefaultData();
            System.out.println("[DataBaseManager] 数据库初始化完成!");
        } else {
    
    
            // 数据库已经存在了, 啥都不必做即可
            System.out.println("[DataBaseManager] 数据库已经存在!");
        }
    }
    // 删除数据库,  及删除文件 也删除目录 
    public void deleteDB() {
    
    
        File file = new File("./data/meta.db");
        boolean ret = file.delete();
        if (ret) {
    
    
            System.out.println("[DataBaseManager] 删除数据库文件成功!");
        } else {
    
    
            System.out.println("[DataBaseManager] 删除数据库文件失败!");
        }
        File dataDir = new File("./data");
        // 使用 delete 删除目录的时候, 需要保证目录是空的.
        ret = dataDir.delete();
        if (ret) {
    
    
            System.out.println("[DataBaseManager] 删除数据库目录成功!");
        } else {
    
    
            System.out.println("[DataBaseManager] 删除数据库目录失败!");
        }
    }


    // 检查是否存在meta.db 文件
    private boolean checkDBExists() {
    
    
        File file = new File("./data/meta.db");
        return file.exists();
    }
    // 这个方法用来建表.
    // 建库操作并不需要手动执行. (不需要手动创建 meta.db 文件)
    // 首次执行这里的数据库操作的时候, 就会自动的创建出 meta.db 文件来 (MyBatis 帮我们完成的)
    private void createTable() {
    
    
        mateMapper.createExchangeTable();
        mateMapper.createQueueTable();
        mateMapper.createBindingTable();
        System.out.println("[DataBaseManager] 创建表完成!");
    }
    // 给数据库表中, 添加默认的数据.
    // 此处主要是添加一个默认的交换机.
    // RabbitMQ 里有一个这样的设定: 带有一个 匿名 的交换机, 类型是 DIRECT.
    private void createDefaultData() {
    
    
        // 先构建一个交换机
        Exchange exchange = new Exchange();
        exchange.setName("");
        exchange.setType(ExchangeType.direct);
        exchange.setDurable(true);
        exchange.setAutoDelete(false);
        mateMapper.insertExchange(exchange);
        System.out.println("[DataBaseManager] 创建初始数据完成!");
    }

    public void insertExchange(Exchange exchange){
    
    
        mateMapper.insertExchange(exchange);
    }
    public List<Exchange> selectAllExchanges(){
    
    
       return mateMapper.selectAllExchanges();
    }
    public void deleteExchange(String exchangeName){
    
    
        mateMapper.deleteExchange(exchangeName);
    }
    public void insertQueue(MSGQueue queue){
    
    

        mateMapper.insertQueue(queue);
    }
    public List<MSGQueue> selectAllQueues(){
    
    
        return mateMapper.selectAllQueues();
    }
    public void deleteQueue(String queueName){
    
    

        mateMapper.deleteQueue(queueName);
    }
    public void insertBinding(Binding binding){
    
    
        mateMapper.insertBinding(binding);
    }
    public List<Binding> selectAllBindings(){
    
    
       return mateMapper.selectAllBindings();
    }
    public void deleteBinding(Binding binding){
    
    
        mateMapper.deleteBinding(binding);
    }
}


Another way to get the Bean object

For the explanation of the DataBaseManager class, we know that if we want to get the Bean object, we usually use the @Autowired annotation, but we want to manually operate this class, and use @Autowired to save it from the beginning, so we teach you another A way to get a Bean object

Step 1: Find the startup class, and add a static member public static ConfigurableApplicationContext context in the startup class
;
Step 2: Use context equal to the result of the run method
Step 3: Use context in DataBaseManager to implement object assembly
mateMapper = MqApplication.context.getBean(MateMapper .class);

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MqApplication {
    
    
	// 在启动类创建一个静态成员, 用来手动的获取bean对象
	public static ConfigurableApplicationContext context;

	public static void main(String[] args) {
    
    
		context = SpringApplication.run(MqApplication.class, args);
	}

}

Unit test the database

But we, every time we finish writing a module, we should unit test the module, and
then we unit test the database.
The unit test is to click Generate in the class you want to test, and a Test will appear. Click
insert image description here
insert image description here
Test Test (install the Junit plug-in - I won't introduce it here), then select the method you want to test, click OK
insert image description here
to generate the corresponding class in the Test package, add @SpringBootTest annotation to this class, and it can be used normally
insert image description here
The test code is as follows

package com.example.demo.mqServer.dataCenter;

import com.example.demo.MqApplication;
import com.example.demo.mqServer.core.Binding;
import com.example.demo.mqServer.core.Exchange;
import com.example.demo.mqServer.core.ExchangeType;
import com.example.demo.mqServer.core.MSGQueue;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class DataBaseManagerTest {
    
    
    private DataBaseManager dataBaseManager = new DataBaseManager();

    // 接下来下面这里需要编写多个 方法 . 每个方法都是一个/一组单元测试用例.
    // 还需要做一个准备工作. 需要写两个方法, 分别用于进行 "准备工作" 和 "收尾工作"

    // 使用这个方法, 来执行准备工作. 每个用例执行前, 都要调用这个方法.
    @BeforeEach
    public void setUp() {
    
    
        // 由于在 init 中, 需要通过 context 对象拿到 metaMapper 实例的.
        // 所以就需要先把 context 对象给搞出来.
        MqApplication.context = SpringApplication.run(MqApplication.class);
        dataBaseManager.init();
    }

    // 使用这个方法, 来执行收尾工作. 每个用例执行后, 都要调用这个方法.
    @AfterEach
    public void tearDown() {
    
    
        // 这里要进行的操作, 就是把数据库给清空~~ (把数据库文件, meta.db 直接删了就行了)
        // 注意, 此处不能直接就删除, 而需要先关闭上述 context 对象!!
        // 此处的 context 对象, 持有了 MetaMapper 的实例, MetaMapper 实例又打开了 meta.db 数据库文件.
        // 如果 meta.db 被别人打开了, 此时的删除文件操作是不会成功的 (Windows 系统的限制, Linux 则没这个问题).
        // 另一方面, 获取 context 操作, 会占用 8080 端口. 此处的 close 也是释放 8080.
        MqApplication.context.close();
        dataBaseManager.deleteDB();
    }

    @Test
    public void testInitTable() {
    
    
        // 由于 init 方法, 已经在上面 setUp 中调用过了. 直接在测试用例代码中, 检查当前的数据库状态即可.
        // 直接从数据库中查询. 看数据是否符合预期.
        // 查交换机表, 里面应该有一个数据(匿名的 exchange); 查队列表, 没有数据; 查绑定表, 没有数据.
        List<Exchange> exchangeList = dataBaseManager.selectAllExchanges();
        List<MSGQueue> queueList = dataBaseManager.selectAllQueues();
        List<Binding> bindingList = dataBaseManager.selectAllBindings();

        // 直接打印结果, 通过肉眼来检查结果, 固然也可以. 但是不优雅, 不方便.
        // 更好的办法是使用断言.
        // System.out.println(exchangeList.size());
        // assertEquals 判定结果是不是相等.
        // 注意这俩参数的顺序. 虽然比较相等, 谁在前谁在后, 无所谓.
        // 但是 assertEquals 的形参, 第一个形参叫做 expected (预期的), 第二个形参叫做 actual (实际的)
        Assertions.assertEquals(1, exchangeList.size());
        Assertions.assertEquals("", exchangeList.get(0).getName());
        Assertions.assertEquals(ExchangeType.direct, exchangeList.get(0).getType());
        Assertions.assertEquals(0, queueList.size());
        Assertions.assertEquals(0, bindingList.size());
    }

    private Exchange createExchange(String name){
    
    
        Exchange exchange = new Exchange();
        exchange.setName(name);
        exchange.setAutoDelete(false);
        exchange.setDurable(true);
        exchange.setType(ExchangeType.fanout);
        exchange.setArguments("aaa",1);
        exchange.setArguments("bbb",2);
        return exchange;

    }
    @Test
    public void insertExchange() {
    
    
        Exchange exchange =createExchange("testExchange");
        dataBaseManager.insertExchange(exchange);
        // 插入完毕之后, 查询结果
        List<Exchange> exchangeList = dataBaseManager.selectAllExchanges();
        Assertions.assertEquals(2, exchangeList.size());
        Exchange newExchange = exchangeList.get(1);
        Assertions.assertEquals("testExchange", newExchange.getName());
        Assertions.assertEquals(ExchangeType.fanout, newExchange.getType());
        Assertions.assertEquals(false, newExchange.isAutoDelete());
        Assertions.assertEquals(true, newExchange.isDurable());
        Assertions.assertEquals(1, newExchange.getArguments("aaa"));
        Assertions.assertEquals(2, newExchange.getArguments("bbb"));
        System.out.println("insertExchange测试成功");
    }
    @Test
    public void testDeleteExchange() {
    
    
        // 先构造一个交换机, 插入数据库; 然后再按照名字删除即可!
        Exchange exchange =createExchange("testExchange");
        dataBaseManager.insertExchange(exchange);
        List<Exchange> exchangeList = dataBaseManager.selectAllExchanges();
        Assertions.assertEquals(2, exchangeList.size());
        Assertions.assertEquals("testExchange", exchangeList.get(1).getName());

        // 进行删除操作
        dataBaseManager.deleteExchange("testExchange");
        // 再次查询
        exchangeList = dataBaseManager.selectAllExchanges();
        Assertions.assertEquals(1, exchangeList.size());
        Assertions.assertEquals("", exchangeList.get(0).getName());
        System.out.println("testDeleteExchange测试成功");
    }

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

    @Test
    public void testInsertQueue() {
    
    
        MSGQueue queue = createTestQueue("testQueue");
        dataBaseManager.insertQueue(queue);

        List<MSGQueue> queueList = dataBaseManager.selectAllQueues();

        Assertions.assertEquals(1, queueList.size());
        MSGQueue newQueue = queueList.get(0);
        Assertions.assertEquals("testQueue", newQueue.getName());
        Assertions.assertEquals(true, newQueue.isDurable());
        Assertions.assertEquals(false, newQueue.isAutoDelete());
        Assertions.assertEquals(false, newQueue.isExclusive());
        Assertions.assertEquals(1, newQueue.getArguments("aaa"));
        Assertions.assertEquals(2, newQueue.getArguments("bbb"));
        System.out.println("testInsertQueue测试成功");
    }
    @Test
    public void testDeleteQueue() {
    
    
        MSGQueue queue = createTestQueue("testQueue");
        dataBaseManager.insertQueue(queue);
        List<MSGQueue> queueList = dataBaseManager.selectAllQueues();
        Assertions.assertEquals(1, queueList.size());
        // 进行删除
        dataBaseManager.deleteQueue("testQueue");
        queueList = dataBaseManager.selectAllQueues();
        Assertions.assertEquals(0, queueList.size());
        System.out.println("testDeleteQueue测试成功");
    }

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

    @Test
    public void testInsertBinding() {
    
    
        Binding binding = createTestBinding("testExchange", "testQueue");
        dataBaseManager.insertBinding(binding);

        List<Binding> bindingList = dataBaseManager.selectAllBindings();
        Assertions.assertEquals(1, bindingList.size());
        Assertions.assertEquals("testExchange", bindingList.get(0).getExchangeName());
        Assertions.assertEquals("testQueue", bindingList.get(0).getMsgQueueName());
        Assertions.assertEquals("testBindingKey", bindingList.get(0).getBindingKey());
        System.out.println("testInsertBinding测试成功");

    }

    @Test
    public void testDeleteBinding() {
    
    
        Binding binding = createTestBinding("testExchange", "testQueue");
        dataBaseManager.insertBinding(binding);
        List<Binding> bindingList = dataBaseManager.selectAllBindings();
        Assertions.assertEquals(1, bindingList.size());

        // 删除
        Binding toDeleteBinding = createTestBinding("testExchange", "testQueue");
        dataBaseManager.deleteBinding(toDeleteBinding);
        bindingList = dataBaseManager.selectAllBindings();
        Assertions.assertEquals(0, bindingList.size());
        System.out.println("testDeleteBinding测试成功");
    }
}

Guess you like

Origin blog.csdn.net/qq_56454895/article/details/132154787