2026/5/21 21:49:04
网站建设
项目流程
python做的知名网站,只做网站的人员工资,云建站优势,在线设计公司考虑数据库的使用:
本次项目采用的是相比于 MySQL更加轻量的数据库 SQLite,SQLite的是用也是非常的广泛,在一些性能不高的产品中的使用频率是非常高的,嵌入式设备,比如 Andioid系统,就是内置的 SQLite
SQLite 的轻量化体现在,一个完整的 SQLite 数据库,只有一个单独的可执行…考虑数据库的使用:本次项目采用的是相比于 MySQL更加轻量的数据库 SQLite,SQLite的是用也是非常的广泛,在一些性能不高的产品中的使用频率是非常高的,嵌入式设备,比如 Andioid系统,就是内置的 SQLiteSQLite 的轻量化体现在,一个完整的 SQLite 数据库,只有一个单独的可执行的文件不到1M,而且SQLite是一个本地的数据库,这个数据库直接操作的是本地的硬盘文件在 Java 要中要想使用 SQLite 不用额外安装,引入相关的依赖即可,对于SQLite来说,在进行配置相关内容的时候是不需要指定用户名和密码的,它的数据是存放在本地的硬盘文件中的,和网络无关,SQLite虽然与MySQL存在不同,但是二者都是可以通过 MyBatis 这样的框架来使用的建库(数据库文件,就是数据库),建表 当上述配置和依赖都准备好了之后,程序启动就会自动的建库建表设计:核心数据库表有这几个:交换机存储,队列存储,绑定存储针对于这几个核心类,很容易把表设计出来,但是具体是什么时机来执行上述操作? 按照以往的操作是先把数据库表直接创建好,在启动服务器,这些操作都是在部署阶段完成的,之前的操作部署一次即可,不会反复的进行操作,但是后续接触到的更多的程序可能会反复部署多次,能够简化部署的步骤,也是很关键的,在这个项目中,我们通过代码的方式来完成自动的建表操作?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.zcfe.mq.mqserver.mapper.MetaMapper update idcreateExchangeTable create table if not exists exchange ( name varchar(50) primary key, type int, durable boolean, autoDelete boolean, arguments varchar(1024) ); /update update idcreateQueueTable create table if not exists queue ( name varchar(50) primary key, durable boolean, exclusive boolean, autoDelete boolean, arguments varchar(1024) ); /update update idcreateBindingTable create table if not exists binding ( exchangeName varchar(50), queueName varchar(50), bindingKey varchar(256) ); /update insert idinsertExchange parameterTypecom.zcfe.mq.mqserver.core.Exchange insert into exchange values(#{name}, #{type}, #{durable}, #{autoDelete}, #{arguments}); /insert select idselectAllExchange resultTypecom.zcfe.mq.mqserver.core.Exchange select * from exchange; /select delete iddeleteExchange parameterTypejava.lang.String delete from exchange where name #{exchangeName}; /delete insert idinsertQueue parameterTypecom.zcfe.mq.mqserver.core.MSGQueue insert into queue values(#{name}, #{durable}, #{exclusive}, #{autoDelete}, #{arguments}); /insert select idselectAllQueues resultTypecom.zcfe.mq.mqserver.core.MSGQueue select * from queue; /select delete iddeleteQueue parameterTypejava.lang.String delete from queue where name #{queueName}; /delete insert idinsertBinding parameterTypecom.zcfe.mq.mqserver.core.Binding insert into binding values(#{exchangeName}, #{queueName}, #{bindingKey}); /insert select idselectAllBinding resultTypecom.zcfe.mq.mqserver.core.Binding select * from binding; /select delete iddeleteBinding parameterTypecom.zcfe.mq.mqserver.core.Binding delete from binding where exchangeName #{exchangeName} and queueName #{queueName}; /delete /mapper1.当前,是把每一个建表的语句,都单独列为一个 update 标签,并且对应一个 java 方法,能否改成,一个 update 标签中包含多个建表语句,同时借助一个 java 方法,完成上述多个表的创建呢?其实在 MyBstis 中是支持这样的操作,一个标签中包含多个 sql 语句的(前提是MySQL 或者 Oracle) 对于 SQLite 无法做到上述的功能,当你一个 update 标签中,写了多个 create table 语句的时候,只有第一个语句能执行private MapString, Object arguments new HashMap(); public String getArguments() { //是把当前的 arguments 参数,从 Map 转成 String (json) ObjectMapper objectMapper new ObjectMapper(); try { return objectMapper.writeValueAsString(arguments); } catch (JsonProcessingException e) { e.printStackTrace(); } //如果代码真的出现了异常, 就返回一个空的 json 字符串 return {}; } //这个方法,是从数据库读取数据之后,构造的 Exchange 对象,会自动的调用到 public void setArguments(String argumentsJson) { ObjectMapper objectMapper new ObjectMapper(); //其中的第二个参数,用来描述当前 json 字符串,要转成的 java 对象是啥类型的 //如果是一个简单的类型,直接使用对应的类型的类对象即可 //如果是集合类这样的复杂类型,可以使用 TypeReference 匿名内部类对象 //来描述复杂类型的具体信息(通过泛型来描述的) try { this.arguments objectMapper.readValue(argumentsJson, new TypeReferenceHashMapString, Object() {}); } catch (JsonProcessingException e) { e.printStackTrace(); } }如何实现 arguments 这件键值对,和数据库中的字符串类型相互转化呢?关键的要点在于 MyBaits 在完成数据库操作的时候,会自动的调用对象的 getter 和 setter 操作1.比如 MyBatis 往数据库中写数据的时候,就会调用对象的 getter 方法,拿到属性的值,在往数据库中写,如果这个过程中,让 getArguments 得到的结果是 String 类型的,此时就可以直接把这个数据写进数据库中2.比如 MyBatis 从数据库中读数据的时候,就会调用对象的 setter 方法, 把数据库中读到的结果设置到对象的属性中,比如这个过程中,让 setArguments 参数是一个 String,并且在 setArguments 内部针对字符串进行解析,解析成一个 Map 对象try { this.arguments objectMapper.readValue(argumentsJson, new TypeReferenceHashMapString, Object() {}); } catch (JsonProcessingException e) { e.printStackTrace(); }第二个参数HashMapString, Object() 用来描述当前 json 字符串,要转成的java对象是啥类型的,如果是一个简单类型,就可以直接使用对应的类型类对象即可,如果是一个集合类这样的复杂类型,可以使用 TypeReference 匿名内部类对象的方式,来描述复杂类型的具体信息(通过泛型参数来描述的)写一个类,整合上述的数据库操作一般谈到初始化,会用到 构造方法,但是我们此处是一个单独的普通方法构造方法,一般是用来初始化类的属性,一般不太会涉及到太多的业务逻辑,此处的初始化,带有业务逻辑,还是单独拎出来,手动调用比较合适一些我们期望的是,在咱们得BrokerServer启动的时候,做出一下逻辑判定:1.如果数据库已经存在了(表啥的都有了),不做任何操作2.如果数据库不存在则建库建表,构造默认数据//针对数据库进行初始化 public void init() { //手动获取到 MetaMapper(防止空指针异常的情况出现) metaMapper MqApplication.context.getBean(MetaMapper.class); if (!checkDBExists()) { //数据不存在,就进行建库建表操作 //先创建一个 data 目录 File dataDir new File(./data); dataDir.mkdirs(); //创建表 createTable(); //插入数据 createDefaultData(); System.out.println([DataBaseManager]数据库初始化完成); } else { //数据库存在,啥都不用干, System.out.println([DataBaseManager]数据库初始化完成); }1,啥叫存在? 就是指 判定 meta.db 这个文件是否存在即可针对 DataBaseManage 进行单元测试设计测试用例的时候,要求单元测试用例和用例之间,是需要相互独立的,不会干扰的//这个方法,来执行准备工作,每个用例执行前,都要调用这个方法 BeforeEach public void setUp() { MqApplication.context SpringApplication.run(MqApplication.class); dataBaseManager.init(); } //这个方法,来处理收尾工作,每个用例执行后,都要调用这个方法 AfterEach public void tearDown() { //这里要进行的操作就是把数据库中的数据删除(也就是把数据库文件, meta.db 直接删除了就行) //注意, 这里不能直接就删除,要先关闭上述的 context 对象 //此处的 context 对象持有了 MetaMapper 的实例,而 MetaMapper 由打开了 meta.db 数据库文件 //如果 meta.db 被别人打开了,此时删除数据库文件(meta.db)是会失败的,(这是受限于window的操作系统) //另一方面,获取context会占用8080窗口,此处释放也是为了后面能够继续使用这个窗口 MqApplication.context.close(); dataBaseManager.deleteDB(); }Test public void testInitTable() { //由于 init 方法,已经在前面 setUp 调用过了, 直接在测试用例的代码中检查,数据库的状态即可 //直接从数据库中进行查询查看是否符合预期 //查交换机里面应该有一个数据(匿名的 Exchange), 查队列,没有数据,查绑定也没有数据 ListExchange exchangesList dataBaseManager.selectAllExchange(); ListMSGQueue queueList dataBaseManager.selectAllQueue(); ListBinding bindingList dataBaseManager.selectAllBinding(); //这里通过断言来判定结果 //注意这里的两个参数的顺序,比较相等,谁在前谁在后,是没关系的 //这里 assertEquals 的形参,第一个形参是 expected(预期的),第二个形参是 actual(实际的) Assertions.assertEquals(1, exchangesList.size()); Assertions.assertEquals(, exchangesList.get(0).getName()); Assertions.assertEquals(ExchangeType.DIRECT, exchangesList.get(0).getType()); Assertions.assertEquals(0, queueList.size()); Assertions.assertEquals(0, bindingList.size()); }public Exchange createTestExchange(String exchangeName) { Exchange exchange new Exchange(); exchange.setName(exchangeName); exchange.setType(ExchangeType.FANOUT); exchange.setDurable(true); exchange.setAutoDelete(false); exchange.setArguments(aaa, 111); exchange.setArguments(bbb, 222); return exchange; } Test public void testInsertExchange(){ //构造一个 Exchange 对象,插入到数据库中,在查询出来,看是否符合预期 Exchange exchange createTestExchange(testExchange); dataBaseManager.insertExchange(exchange); //插入完毕,查询结果 ListExchange exchangeList dataBaseManager.selectAllExchange(); Assertions.assertEquals(2, exchangeList.size()); //这里获取第二个元素,就是刚刚插入的元素 Exchange newExchange exchangeList.get(1); Assertions.assertEquals(testExchange, newExchange.getName()); Assertions.assertEquals(ExchangeType.FANOUT, newExchange.getType()); Assertions.assertEquals(true, newExchange.isDurable()); Assertions.assertEquals(false, newExchange.isAutoDelete()); Assertions.assertEquals(111, newExchange.getArguments(aaa)); Assertions.assertEquals(222, newExchange.getArguments(bbb)); } Test public void testDeleteExchange() { //先创建一个交换机,插入数据,然后在按照名字删除即可 Exchange exchange createTestExchange(testExchange); dataBaseManager.insertExchange(exchange); ListExchange exchangeList dataBaseManager.selectAllExchange(); Assertions.assertEquals(2, exchangeList.size()); Assertions.assertEquals(testExchange, exchangeList.get(1).getName()); //进行删除操作 dataBaseManager.deleteExchange(testExchange); Assertions.assertEquals(1, dataBaseManager.selectAllExchange().size()); //只剩下一个默认交换机 Assertions.assertEquals(, exchangeList.get(0).getName()); }public MSGQueue createTestQueue(String queueName) { MSGQueue queue new MSGQueue(); queue.setName(queueName); queue.setDurable(true); queue.setAutoDelete(false); queue.setExclusive(false); queue.setArguments(aaa, 111); queue.setArguments(bbb, 222); return queue; } Test public void testInsertQueue() { MSGQueue queue createTestQueue(testQueue); dataBaseManager.insertQueue(queue); ListMSGQueue queueList dataBaseManager.selectAllQueue(); Assertions.assertEquals(1, queueList.size()); Assertions.assertEquals(testQueue, queueList.get(0).getName()); Assertions.assertEquals(true, queueList.get(0).isDurable()); Assertions.assertEquals(false, queueList.get(0).isExclusive()); Assertions.assertEquals(false, queueList.get(0).isAutoDelete()); Assertions.assertEquals(111, queueList.get(0).getArguments(aaa)); Assertions.assertEquals(222, queueList.get(0).getArguments(bbb)); } Test public void testDeleteQueue() { MSGQueue queue createTestQueue(testQueue); dataBaseManager.insertQueue(queue); ListMSGQueue queueList dataBaseManager.selectAllQueue(); Assertions.assertEquals(1, queueList.size()); Assertions.assertEquals(testQueue, queueList.get(0).getName()); //进行删除操作 dataBaseManager.deleteQueue(testQueue); Assertions.assertEquals(0, dataBaseManager.selectAllQueue().size()); }public Binding createTestBinding(String exchangeName, String queueName) { Binding binding new Binding(); binding.setExchangeName(exchangeName); binding.setQueueName(queueName); binding.setBindingKey(testBindingKey); return binding; } Test public void testInsertBinding() { Binding binding createTestBinding(testExchange, testQueue); dataBaseManager.insertBinding(binding); ListBinding bindingList dataBaseManager.selectAllBinding(); Assertions.assertEquals(1, bindingList.size()); Assertions.assertEquals(testExchange, bindingList.get(0).getExchangeName()); Assertions.assertEquals(testQueue, bindingList.get(0).getQueueName()); Assertions.assertEquals(testBindingKey, bindingList.get(0).getBindingKey()); } Test public void testDeleteBinding() { Binding binding createTestBinding(testExchange, testQueue); dataBaseManager.insertBinding(binding); ListBinding bindingList dataBaseManager.selectAllBinding(); Assertions.assertEquals(1, bindingList.size()); Assertions.assertEquals(testExchange, bindingList.get(0).getExchangeName()); Assertions.assertEquals(testQueue, bindingList.get(0).getQueueName()); Assertions.assertEquals(testBindingKey, bindingList.get(0).getBindingKey()); //进行删除操作 dataBaseManager.deleteBinding(binding); Assertions.assertEquals(0, dataBaseManager.selectAllBinding().size()); }