索引
1.较频繁的查询条件字段应该创建索引
2.唯一性太差的字段不适合单独创建索引 即使频繁查询条件
3.更新频繁的字段不适合创建索引
4.不会出现在where子句中字段不该创建索引
-- 创建索引
CREATE TABLE t (
id INT ,
`name` VARCHAR(32));
-- 查询表是否有索引
SHOW INDEXES FROM 表名;
-- 添加索引
# create index 索引名 on 表名 (列名)
# alter table 表名 add index 索引名 (列名)
-- 添加普通索引方式1
CREATE INDEX id_index ON t (id);
-- 添加普通索引方式2
ALTER TABLE t ADD INDEX id_index (id);
-- 添加唯一索引
CREATE UNIQUE INDEX id_index ON t (id);
-- 如何选择
-- 1. 如果某列的值,是不会重复的,则优先考虑使用unique索引, 否则使用普通索引
-- 添加主键索引
CREATE TABLE a (
id INT ,
`name` VARCHAR(32));
ALTER TABLE a ADD PRIMARY KEY (id)
-- 删除索引
# drop index 索引名 ON 表名
DROP INDEX id_index ON t
-- 删除主键索引
# alter table 表名 drop primary key
ALTER TABLE a DROP PRIMARY KEY
-- 修改索引 先删除 在添加新的索引
-- 查询索引
-- 1. 方式
SHOW INDEX FROM t
-- 2. 方式
SHOW INDEXES FROM t
-- 3. 方式
SHOW KEYS FROM t
-- 4 方式
DESC t
MySQL索引分类
数据结构维度
B+Tree Hash FullText R-Tree
物理存储维度
聚簇索引(依靠B+树) 非聚簇索引
字段约束维度
主键索引 唯一索引 普通索引 前缀索引
索引组成维度
单列索引 联合索引
索引失效的情况
1. 在where条件语句 '=' 的左边进行函数、运算符或表达式的计算
2. 不推荐使用like操作
like '%aaa%' 和 like '%aaa' 都不会使用索引
而 like 'aaa%' 可以使用索引
3. 避免对字段进行null的判断 (可以用一个值代替null,如-999)
4. 避免使用or,可以用union替代
如果使用or还要让索引生效 or条件中的每个列都必须加上索引
5. 使用exist代替in
表中数据越多,exist的效率就比in要越大
6. 联合索引要符合最左前缀原则
例如: 一个表a,b,c,d,e列,由三个字段 a,b,c 组成联合索引 idx_a_b_c
索引生效: SELECT * FROM table_name WHERE a = 1 AND b = 2 AND c = 5
索引生效: SELECT * FROM table_name WHERE b = 2 AND a = 1 AND c = 5
索引生效: SELECT * FROM table_name WHERE a = 1
索引失效: SELECT * FROM table_name WHERE b = 2 AND c = 5
索引失效: SELECT * FROM table_name WHERE c = 5
部分生效: SELECT * FROM table_name WHERE a = 1 AND c = 5
部分生效: SELECT * FROM table_name WHERE a = 1 AND b > 2 AND c = 5
事务
start transaction 开始一个事务
savepoint 设置保存点
rollback to 回退事务
rollback 回退全部事务
commit 提交事务 所有操作生效 不能回退
-- 1. 创建一张测试表
CREATE TABLE t
( id INT,
`name` VARCHAR(32));
-- 2. 开始事务
START TRANSACTION
-- 3. 设置保存点
SAVEPOINT a
-- 执行dml 操作
INSERT INTO t VALUES(100, 'tom');
SELECT * FROM t;
-- 3. 设置保存点
SAVEPOINT b
-- 执行dml操作
INSERT INTO t VALUES(200, 'jack');
-- 4.回退到 b
ROLLBACK TO b
-- 4.继续回退 a
ROLLBACK TO a
-- 4.直接回退到事务开始的状态.
ROLLBACK
-- 5.提交事务 所有操作生效不能回退
COMMIT
事务细节
#1.如果不开始事务 默认情况下 dml操作是自动提交的 不能回滚
-- 自动提交 commit
INSERT INTO t VALUES(300, 'milan');
#2. 如果开始一个事务,你没有创建保存点. 你可以执行rollback,
-- 默认就是回退到你事务开始的状态
START TRANSACTION
INSERT INTO t VALUES(400, 'king');
INSERT INTO t VALUES(500, 'scott');
-- 表示直接回退到事务开始的的状态
ROLLBACK
COMMIT;
#3.你也可以在这个事务中(还没有提交时),
-- 创建多个保存点.比如: savepoint a;
-- 执行dml, savepoint b
#4.你可以在事务没有提交前,选择回退到哪个保存点
#5.InnoDB 存储引擎支持事务, MyISAM不支持
#6.开始一个事务 start transaction, set autocommit=off;
事务四大特性
事务:
生活中的事务: 指的是比较正式的事情
数据库中的事务: 指的是一组最小逻辑操作单元,这个操作它包含了很多步骤,组成这个事务的这些步骤,是整体不可再分割的,这些步骤要么同时成功,要么同时失败
转账: 张三给李四转账1000元
1.张三的账户上减去1000元
出现异常
2.李四的账户上增加1000元
上面减钱和加钱这两步操作 必须在同一事务中进行。
事务的四大特性(ACID):
1.原子性(Atomicity):
原子性是指事务是一个不可分割的工作单位
事务中的操作要么都发生,要么都不发生
2.一致性:
事务必须使数据库从一个一致性状态变换到另外一个一致性状态
3.隔离性:
事务的隔离性是多个用户并发访问数据库时
数据库为每一个用户开启的事务
不能被其他事务的操作数据所干扰
多个并发事务之间要相互隔离
4.持久性:
持久性是指一个事务一旦被提交
它对数据库中数据的改变就是永久性的
接下来即使数据库发生故障也不应该对其有任何影响
默认情况下,Connection对象处于自动提交模式下
这意味着它在执行每个语句后都会自动提交更改。
如果禁用了自动提交模式,那么要提交更改就必须显式调用commit方法
否则无法保存数据库更改。
//void setAutoCommit ( boolean autoCommit)
throws SQLException将此连接的自动提交模式设置为给定状态
如果连接处于自动提交模式下,则它的所有SQL语句将被执行并作为单个事务提交。
否则,它的SQL语句将聚集到事务中,
直到调用commit方法或rollback方法为止。
默认情况下,新连接处于自动提交模式。
事务隔离级别
★不考虑隔离性会出现的读问题
脏读:
在一个事务中读取到另一个事务没有提交的数据
不可重复读:
在一个事务中,两次查询的结果不一致(针对的update操作)
不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。
虚读(幻读):
在一个事务中,两次查询的结果不一致(针对的insert操作)
无法演示出来,MySQL已经默认避免了
★MySQL四种隔离级别
通过设置数据库的隔离级别来避免上面的问题
read uncommitted 读未提交 上面的三个问题都会出现
read committed 读已提交 可以避免脏读的发生Oracle默认级别
repeatable read 可重复读 可以避免脏读和不可重复读的发生MySQL默认级别
serializable 串行化 可以避免所有的问题
●演示脏读的发生:
将数据库的隔离级别设置成 读未提交
set session transaction isolation level read uncommitted;
查看数据库的隔离级别
select @@tx_isolation;
演示:
打开两个窗口进行演示: 给两个窗口设置好相同的隔离级别
开启事务: start transaction;
修改数据: update bank set money=1500 where username='lisi';
让另一个窗口开启事务 查询数据 他查到了 就是脏读
我这边窗口 一回滚(rollback),钱又没过去
●避免脏读的发生,将隔离级别设置成 读已提交
set session transaction isolation level read committed;
不可避免不可重复读的发生
●避免不可重复读的发生 经隔离级别设置成 可重复读
set session transaction isolation level repeatable read;
●演示串行化 可以避免所有的问题
set session transaction isolation level serializable;
我这边的事务不提交,那边的事务无法执行锁表的操作
四种隔离级别的效率
(read uncommitted)>(read committed)>(repeatable read)>(serializable)
四种隔离级别的安全性
(read uncommitted)<(read committed)<(repeatable read)<(serializable)
开发中绝对不允许脏读发生
mysql中默认级别:repeatable read
oracle中默认级别:read committed
java中控制隔离级别:
Connection的api
void setTransactionIsolation(int level)
level是常量
视图
概念:
有结构(有行有列)
但没有结果(结构中不真实存储数据)的虚拟的表,
虚拟表的结构来源不是自己定义
而是从对应的基表中产生(视图数据的来源)
◎创建视图语法:
create view 视图名称 as select语句
#创建单表视图
CREATE VIEW my_v1 AS SELECT * FROM employee;
#创建多表视图 注意:不要查询两张表中的同名字段 不然会报错
create view my_v2
as select a.字段名,b.字段名 from a,b where a.id=b.id;
注意:MySQL中视图不支持封装子查询查出来的数据
查看视图
其实视图是一张 虚拟表 那关于查询表的语句 对视图都是可以用的
show tables;
#显示视图的结构
desc 视图名;
#视图查询语句
SELECT * FROM 视图名;
#查看视图创建语句
show create view 视图名;
视图的使用:
视图的使用,只是为了简化查询,你可以把视图当作表一样去使用
视图的执行:其实本质就是执行封装的select语句
◎删除视图: drop view 视图名
drop view my_v1
◎修改视图:
视图本身不可以修改,但是视图的来源是可以修改的(其实就是修改select语句)
语法: alter view 视图名字 as 新的select语句
视图的意义:
(1) 视图可以节省SQL语句,
将一条复杂的查询语句,
使用视图进行保存,
以后可以直接对视图进行操作
(2) 数据安全,
视图操作注意是针对查询语句的,
如果对视图结构进行处理(比如删除),
不会影响基表的数据,
所以相对来说数据比较安全
(3) 视图往往是在大项目中去使用,
而且是多系统中去使用,
我可以对外提供一些有用的数据,
隐藏一些关键的数据
(4) 视图对外可以提供友好的数据,
不同的视图提供不同的数据,
对外提供的数据好像是经过专门设计的一样
(5) 视图可以更好的进行权限控制
比如对外隐藏我的一些基表的名称
视图数据的操作:
视图是可以进行数据操作的(比如 增,删,改,视图中的数据),但是有很多限制
视图插入数据:
(1)多表视图不能插入数据
(2)单表视图中可以插入数据
如果视图中字段没有基表中不能为空的字段且没有默认值的字段,是插入不成功的
(3)视图是可以向基表中插入数据的
视图的操作是影响基表的
视图删除数据
(1)多表视图不能删除数据
(2)单表视图可以删除数据,也会影响到基表
视图更新数据
单表视图,多表视图都可以更新数据
更新限制:with check option
例如: create view my_v1
as select * from student
where age>30
with check option;
表示视图数据的来源都是年龄大于30的
with check option 决定通过视图更新的时候
不能将已得到数据age>30的学生 改成age<30 的
那么:update my_v1 set age=20 where id=1;
就会报错 不允许改 因为做了限制
存储过程
存储过程是数据库中的一个对象
存储在服务端 用来封装多条SQL语句且带有逻辑性 可以实现一个功能
由于他在创建时 就已经对SQL进行了编译 所以执行效率高
而且可以重复调用 类似与我们Java中的方法
in:输入参数
out:输出参数
inout:输入输出参数
DELIMITER $$
CREATE PROCEDURE `security`.`test2`(IN num INT,OUT res INT)
BEGIN
SELECT * FROM sys_role WHERE id = num;
SELECT COUNT(*) FROM sys_role INTO res;
END $$
DELIMITER ;
CALL `security`.`test2`(1,@res);
SELECT @res;
函数
函数包含了内置函数和自定义函数
函数调用
SELECT 函数名();
删除函数:
DROP FUNCTION 函数名;
函数和存储过程的区别
1.存储过程没有返回值 函数必须要有返回值
但是存储过程可以用out能实现返回值这个作用
2.存储过程有in out inout这几个参数类型
函数的参数全是用来收实参
自定义函数语法
DELIMITER $$
CREATE
FUNCTION `数据库名`.`函数名`()
RETURNS 返回类型
BEGIN
函数逻辑...
END$$
DELIMITER ;
触发器
触发器:
数据库中的一个对象 相当于JS中的监听器
触发器可以监听 增 删 改 三个动作
比如说我想监听一张表,只要我增删改了这张表中的数据,
我就可以触发这个触发器,去往另外一张表中记录一下日志
-- 往一张表test中删除数据
-- 在日志表logger中添加一条记录
DELIMITER $$
CREATE TRIGGER tigger1
AFTER DELETE ON test
FOR EACH ROW
BEGIN
INSERT INTO logger VALUES(NULL,"你删除了一条数据",NOW());
END$$
DELIMITER ;
DELETE FROM employee_enh WHERE emp_no = 25348;
#删除test表中的内容后 触发器启动
mybatis的使用
pom.xml 导入jar包
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.14</version>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
<build>
<plugins> <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
src/main/resources/mybatis/mybatis-config.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>
<settings>
<!--开启驼峰式命名-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
src/main/resources/application.properties
# 应用名称
spring.application.name=airQuality
# 应用服务 WEB 访问端口
server.port=8080
#mybaits的相关配置
#mybatis核心配置文件的路径
mybatis.config-location=classpath:mybatis/mybatis-config.xml
# mybatis mapper 接口的映射文件路径
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
# 实体类的别名
mybatis.type-aliases-package=com.edu.entities
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/airquality?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
#使用德鲁伊数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化大小,最小,最大
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
# 配置获取连接等待超时的时间
spring.datasource.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
src/main/resources/generatorConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="testTables" targetRuntime="MyBatis3" defaultModelType="flat">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/airquality?serverTimezone=UTC"
userId="root"
password="123456">
<!--去除xxxWithBLOBs的影响-->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.edu.entities" targetProject=".\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
<!-- true就可以保证与数据库中的字段一致
false就是驼峰命名法的格式 -->
<property name="useActualColumnNames" value="true"/>
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="mybatis.mapper" targetProject=".\src\main\resources">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.edu.mapper"
targetProject=".\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<!-- 指定数据库表 -->
<!-- <table schema="" tableName="tb_item" domainObjectName="Item"></table>
domainObjectName 可以配置生成的pojo名字
如不需要example类添加下面四个属性 默认为true
enableCountByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" enableUpdateByExample="false"></table> -->
<table tableName="air_quality_index" domainObjectName="AirQualityIndex"/>
<table tableName="district" domainObjectName="District"/>
</context>
</generatorConfiguration>
src/main/java/com/edu/AirQualityMybatisApplication.java
@SpringBootApplication
@MapperScan(basePackages = "com.edu.mapper")
public class AirQualityMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(AirQualityMybatisApplication.class, args);
}
}
src/test/java/com/edu/AirQualityMybatisApplicationTests.java
@SpringBootTest
class AirQualityMybatisApplicationTests {
@Autowired
private AirQualityIndexMapper airQualityIndexMapper;
@Autowired
private DistrictMapper districtMapper;
@Test
void contextLoads() {
//按条件查询
District district = districtMapper.selectByPrimaryKey(1);
System.out.println(district);
}
@Test
void contextLoads1() {
//创建条件查询对象
AirQualityIndexExample airQualityIndexExample = new AirQualityIndexExample();
airQualityIndexExample.createCriteria().andIdBetween(2,4);
List<AirQualityIndex> airQualityIndices = airQualityIndexMapper.selectByExample(airQualityIndexExample);
airQualityIndices.forEach(System.out::println);
}
}
mybatis-plus的使用
pom.xml 导入jar包
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<!--修改mysql驱动版本号-->
<version>5.1.47</version>
</dependency>
<!--mybatis-plus启动器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--mybatis-plus代码生成-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
src/main/resources/application.properties
# 应用名称
spring.application.name=AirQuality_mybatis_plus
# 应用服务 WEB 访问端口
server.port=8080
# 数据库驱动:根据pom.xml文件中的MySQL版本定
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/airquality
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#配置实体类别名
mybatis-plus.type-aliases-package=com.edu.entity
#配置mapper接口对应的xml文件放置的位置
mybatis-plus.mapper-locations=classpath:com/edu/mapper/*.xml"
#配置日志输出级别,输出sql语句
logging.level.org.westos.mapper=debug
src/test/java/com/edu/CodeGenerator.java
public class CodeGenerator {
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
//这里注意加上 useSSL=false
dsc.setUrl("jdbc:mysql://localhost:3306/airquality?useSSL=false");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
// 全局配置
GlobalConfig gc = new GlobalConfig();
//文件生成路径
String path = System.getProperty("user.dir") + "/src/main/java";
System.out.println(path);
gc.setOutputDir(path);
gc.setIdType(IdType.AUTO); //id自增长
gc.setAuthor("作者:李杰");
gc.setFileOverride(true); //覆盖现有的
gc.setOpen(false); //是否生成后打开
gc.setDateType(DateType.ONLY_DATE); //日期字段
mpg.setGlobalConfig(gc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.edu"); //父包名
//设置不同类文件生成的路径,如果你要默认的路径,下面可以不用设置
//==========================
HashMap<String, String> pathMap = new HashMap<>();
//设置实体类生成的位置
pathMap.put(ConstVal.ENTITY_PATH, System.getProperty("user.dir") + "/src/main/java/com/edu/entity");
pathMap.put(ConstVal.CONTROLLER_PATH, System.getProperty("user.dir") + "/src/main/java/com/edu/controller");
//设置Mapper接口生成的位置
pathMap.put(ConstVal.MAPPER_PATH, System.getProperty("user.dir") + "/src/main/java/com/edu/mapper");
//设置Service接口的位置
pathMap.put(ConstVal.SERVICE_PATH, System.getProperty("user.dir") + "/src/main/java/com/edu/service");
//设置Service接口实现类的位置
pathMap.put(ConstVal.SERVICE_IMPL_PATH, System.getProperty("user.dir") + "/src/main/java/com/edu/service");
pc.setPathInfo(pathMap);
//============================================
mpg.setPackageInfo(pc);
// 自定义配置,这里配置 接口对应的mapper文件的输出路径,如果你要默认的位置可以不用设置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return System.getProperty("user.dir") + "/src/main/resources/com/edu/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true); //使用lombok
strategy.setEntitySerialVersionUID(true);// 实体类的实现接口Serializable
strategy.setRestControllerStyle(true); // @RestController
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("tb_"); // 去掉表前缀
mpg.setStrategy(strategy);
//设置模板引擎
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
}
src/main/java/com/edu/AirQualityMybatisPlusApplication.java
@SpringBootApplication
@MapperScan(basePackages = "com.edu.mapper")
public class AirQualityMybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(AirQualityMybatisPlusApplication.class, args);
}
}
src/main/java/com/edu/config/MybatisPlusConfig.java
@Configuration
@EnableTransactionManagement //开启事务管理
@MapperScan("com.edu.mapper") //扫描该包下所有的mapper接口
public class MybatisPlusConfig {
//分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
src/test/java/com/edu/AirQualityMybatisPlusApplicationTests.java
@SpringBootTest
class AirQualityMybatisPlusApplicationTests {
@Autowired
private AirQualityIndexMapper airQualityIndexMapper;
@Autowired
private DistrictMapper districtMapper;
@Test
void contextLoads() {
District district = districtMapper.selectById(2);
System.out.println(district);
HashMap<String, Object> hm = new HashMap<>();
hm.put("id",1);
List<District> districts = districtMapper.selectByMap(hm);
districts.forEach(System.out::println);
//分页查询
Page<District> districtPage = new Page<>(1,3);
districtMapper.selectPage(districtPage, null);
System.out.println(districtPage.getCurrent()+" "+districtPage.getSize());
}
@Test
void contextLoads1() {
//条件构造器
QueryWrapper<AirQualityIndex> qw = new QueryWrapper<>();
qw.in("id",1,2,3);
List<AirQualityIndex> airQualityIndices = airQualityIndexMapper.selectList(qw);
airQualityIndices.forEach(System.out::println);
}
}