【SpringBoot应用篇】SpringBoot+MybatisPlus集成国产DM8(达梦)数据库
- 简介和安装
- 基本概念介绍
- SpringBoot+MP整合DM8
- pom
- yml
- Address
- AddressMapper
- 启动类
- 测试类
- 增
- 删
- 改
- 查
- yml配置与实体类@TableName表映射问题
简介和安装
DM8 是达梦数据库有限公司推出的新一代高性能数据库产品。它具有开放的、可扩展的体系结构,易于使用的事务处理系统,以及低廉的维护成本,是达梦公司完全自主开发的产品。DM8 以 RDBMS 为核心,以 SQL 为标准,是一个能跨越多种软硬件平台、具有大型数据综合管理能力的、高效稳定的通用数据库管理系统。
连接达梦数据库实例安装文档
连接工具,安装达梦数据库已经自带了客户端可视化工具
基本概念介绍
这里主要简单介绍以下几个简单但重要的概念:数据库、实例、用户、表空间、模式、表、角色、数据文件。
数据库:数据存储的物理介质。广义上讲任何存储数据的物理介质都可叫着数据库,例如一个word文档。但实际上,我们说数据库一般是指像MySQL,ORACLE, HBASE等之类的软件系统。这些系统除了提供数据的存储外,还提供一整套相关的工具或接口对存储的数据进行管理。达梦数据库就是这样的一种系统。
数据库实例:已实例化可存储数据的仓库。达梦数据库与MySQL数据库有一个很大的差别就是:MySQL服务启动后通过create database语句创建N个数据库(数据库实例);而达梦数据库一个实例就只能挂一个数据库(即一个实例就是一个数据库),如果想建多个数据库,则需配置启动相应数量的实例。达梦的每个实例有一系列的后台进程和内存结构,这些是相互独立的。
用户:达梦数据库用户是建在实例下的,因为实例相互独立,所有达梦数据库不同的实例下可以有相同的用户名。另外,在达梦数据库中通过create user语句创建用户时,会同时创建一个同名的“模式”。也可以通过create schema语句单独创建模式(特别注意:在Oracle中,用户与schema是一一对应的,不能单独创建模式,要想创建模式得需通过创建一个同名用户来实现),并授权给某个已存在的用户,因此在达梦数据库中用户与模式是1:N的关系。(注:如果先通过create schema创建了模式,再通过create user创建同名用户,不能创建成功。)
表空间:是一个用来管理数据存储的概念,表空间只是和数据文件(ORA或者DBF文件)发生关系,数据文件是物理的,一个表空间可以包含多个数据文件,而一个数据文件只能隶属一个表空间。可以将表空间理解为对应一块物理存储区,专门用来存储数据文件。实例化达梦数据库时,默认会创建MAIN、ROLL、SYSTEM、TEAM及HMAIN五个表空间。ROLL、SYSTEM、TEAM表空间系统自行维护,用户所建表(如果未指定存放表空间的话)默认放在MAIN表空间。用户也可自定义表空间,然后在创建用户时指定为默认表空间;也可以在建表时通过加"tablespace SpaceName"语句动态指定该表的存储表空间。
模式(schema):如果仅使用过MySQL,而没有ORACLE数据库使用经验,这个概念比较难理解。
关于模式,需要记住一下几点:
-
一个用户一般对应一个schema,该用户的schema名等于用户名,并作为该用户缺省schema;
-
一个用户还可以使用其他的schema(Oracle数据库也可通过权限管理实现访问其他schema);
-
创建模式不指定用户时,该模式默认为SYSDBA拥有;
-
在同一模式下不能存在同名对象,但在不同模式中的对象名称可以相同;
-
用户可以直接访问同名模式对象,但如果要要访问其他模式对象,则必须具有对象权限;
-
当用户要访问其他模式对象时,必须附加模式名作后缀(schema.table);
-
用户是用来连接数据库对象,而模式是用来创建及管理对象的。
表:这个就不用说了吧,但要说明的一点是一个表只能属于一个表空间。
角色:在达梦数据库中,每个用户都有角色。它决定了该用户有什么权限,比如DBA,拥有最高权限。补充说明一点是,实例化的达梦数据库默认有3种角色:DBA, PUBLIC,RESOURCE。新建的用户只拥有PUBLIC角色,该角色几乎做不了撒,因此一般新建用户后,需要单独对他(她)进行授权。
数据文件:数据的物理载体。
这里是帮助理解的一段类比说明:
“我们可以把Database看作是一个大仓库,仓库分了很多很多的房间,Schema就是其中的房间,一个Schema代表一个房间,Table可以看作是每个Schema中的床,Table(床)被放入每个房间中,不能放置在房间之外,那岂不是晚上睡觉无家可归了,然后床上可以放置很多物品,就好比 Table上可以放置很多列和行一样,数据库中存储数据的基本单元是Table,现实中每个仓库放置物品的基本单位就是床, User就是每个Schema的主人,(所以Schema包含的是Object,而不是User),user和schema是一一对应的,每个user在没有特别指定下只能使用自己schema(房间)的东西,如果一个user想使用其他schema(房间)的东西,那就要看那个schema(房间)的user(主人)有没有给你这个权限了,或者看这个仓库的老大(DBA)有没有给你这个权限了。换句话说,如果你是某个仓库的主人,那么这个仓库的使用权和仓库中的所有东西都是你的(包括房间),你有完全的操作权,可以扔掉不用的东西从每个房间,也可以放置一些有用的东西到某一个房间,你还可以给每个User分配具体的权限,也就是他到某一个房间能做些什么,是只能看(Read-Only),还是可以像主人一样有所有的控制权(R/W),这个就要看这个User所对应的角色Role了。”—摘自网络
SpringBoot+MP整合DM8
测试使用的是初始化达梦数据库实例为我们创建的一个schema:PERSON
,表:ADDRESS
CREATE TABLE "PERSON"."ADDRESS"
(
"ADDRESSID" INT IDENTITY(1, 1) NOT NULL,
"ADDRESS1" VARCHAR(60) NOT NULL,
"ADDRESS2" VARCHAR(60),
"CITY" VARCHAR(30) NOT NULL,
"POSTALCODE" VARCHAR(15) NOT NULL,
NOT CLUSTER PRIMARY KEY("ADDRESSID")) STORAGE(ON "BOOKSHOP", CLUSTERBTR) ;
pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<dependencies>
<!-- 达梦数据库依赖 -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.1.193</version>
</dependency>
<!-- Mybatis-Plus依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
yml
spring:
datasource:
driver-class-name: dm.jdbc.driver.DmDriver
# 达梦 模式名就相当于库名
url: jdbc:dm://localhost:5236?schema=PERSON&compatibleMode=mysql&characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
#写法二
#url: jdbc:dm://localhost:5236/PERSON&compatibleMode=mysql&characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: SYSDBA
password: 123456789
mybatis-plus:
configuration:
# 驼峰转换 从数据库列名到Java属性驼峰命名的类似映射
map-underscore-to-camel-case: false
# 是否开启缓存
cache-enable: false
# 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
#call-setters-on-nulls: true
# 打印sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Address
@Data
@TableName(value = "PERSON.ADDRESS")
public class Address {
@TableId(value = "ADDRESSID", type = IdType.AUTO)
private Integer addressId;
@TableField("ADDRESS1")
private String address1;
@TableField("ADDRESS2")
private String address2;
@TableField("CITY")
private String city;
@TableField("POSTALCODE")
private String postaLoCode;
}
AddressMapper
public interface AddressMapper extends BaseMapper<Address> {
}
启动类
@MapperScan(basePackages = "cn.zysheep.mapper")
@SpringBootApplication
public class DmApplication {
public static void main(String[] args) {
SpringApplication.run(DmApplication.class, args);
}
}
测试类
@SpringBootTest(classes = DmApplication.class)
public class AddressMapperTest{
@Autowired
DataSource dataSource;
@Autowired(required = false)
AddressMapper addressMapper;
@Test
public void test() throws SQLException {
System.out.println(dataSource.getConnection());
}
}
增
@Test
public void testSave() {
Address address = new Address();
address.setAddress1("长沙");
address.setCity("长沙市天心区");
address.setPostaLoCode("430001");
addressMapper.insert(address);
}
删
@Test
public void testDeleteById() {
addressMapper.deleteById("17");
}
@Test
public void testDelete() {
Address address = new Address();
address.setAddressId(14);
address.setCity("长沙");
detele(address);
}
public void detele(Address address) {
// eq(boolean condition, R column, Object val)
// 第一个参数条件满足才拼接条件
LambdaQueryWrapper<Address> queryWrapper = Wrappers.<Address>lambdaQuery()
.eq(Objects.nonNull(address.getAddressId()), Address::getAddressId, address.getAddressId())
.eq(StringUtils.isNotBlank(address.getCity()), Address::getCity, address.getCity());
addressMapper.delete(queryWrapper);
}
改
@Test
public void testUpdateById() {
Address address = new Address();
address.setAddressId(17);
address.setCity("长沙市芙蓉区");
address.setPostaLoCode("430002");
addressMapper.updateById(address);
}
@Test
public void testUpdate() {
LambdaUpdateWrapper<Address> wrapper = Wrappers.<Address>lambdaUpdate()
.set(Address::getCity, "长沙市岳麓区")
.set(Address::getPostaLoCode,"430001")
.eq(Address::getAddressId,"1");
addressMapper.update(null,wrapper);
}
查
@Test
public void testSelect() {
List<Address> selectList = addressMapper.selectList(Wrappers.emptyWrapper());
System.out.println(selectList);
}
yml配置与实体类@TableName表映射问题
写法一: application.yml
# 写法一
spring:
datasource:
url: jdbc:dm://localhost:5236?schema=PERSON
实体类,@TableName
可以不指定schema
@Data
@TableName(value = "ADDRESS")
public class Address {
}
写法二: application.yml
# 写法二
spring:
datasource:
url: jdbc:dm://localhost:5236/PERSON
实体类,@TableName
必须指定schema,否则会找不到表
@Data
@TableName(value = "PERSON.ADDRESS")
public class Address {
}
实际开发中不管yml配置使用什么方式,都强烈建议
@TableName(value = "PERSON.ADDRESS")
指定schema。