MySQL
MySQL 关联随机查询
SELECT a.*, b.* FROM a LEFT JOIN b ON a.id = b.info_id AND RAND() < 0.5;
这个查询将使用RAND()
函数来随机关联 b 表中的数据,只有当RAND()
函数返回值小于 0.5 时才会进行关联。这样可以让每次查询的结果都不同,从而达到随机的效果。可以根据需要修改RAND()
函数的参数来控制随机程度。
SQLite 创建数据库
sqlite>.open test.db
SQLite 导入 Navicat
直接将.db
文件拖入空白区域
SQLite 中创建除 main 数据库之外的数据库
在 SQLite 中,默认情况下,每个数据库文件都只有一个主要的数据库(也称为 "main")。 以下是通过 SQLite 的 ATTACH 命令附加其他数据库文件的示例: ATTACH DATABASE 'path/to/database.db' AS alias;
其中,path/to/database.db
是要附加的数据库文件的路径,alias 是你自定义的这个附加数据库的别名(用于区分不同的数据库)。附加数据库后,你可以使用别名指定特定的数据库进行操作,例如:
- 在主要数据库(main)上执行:
SELECT * FROM table_name;
- 在附加的数据库上执行:
SELECT * FROM alias.table_name;
连接池连接数合理设置
最大连接数和最小空闲连接数的合理设置需要综合考虑以下几个因素:
并发请求量:每秒 10 次的 SQL 请求并发量相对较低,因此不需要过多的连接来处理请求。一般来说,最大连接数可以设置为并发请求数的 2 倍左右,即 20 个连接。
硬件资源:如果以 4 核 16 GB 作为参考。假设每个连接占用的内存和 CPU 资源较少,可以考虑将最大连接数适当调高,但要注意不要超过硬件资源的承载能力。在 16 GB内存下,可以适度增加最大连接数,例如设置为 30~40 个连接。
数据库服务器性能:除了硬件资源外,还需考虑数据库服务器的性能。如果数据库服务器的处理能力较弱,建议将最大连接数适当降低,以避免过多的连接导致性能下降。可以通过监测数据库服务器负载情况和性能指标来评估最大连接数合适的范围。
MP 执行时输出SQL语句
# application.yml文件中配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
MP 查询条件为空字符串或 null 不加入此查询条件中
mybatis-plus 的条件构造器方法 eq()
、like()
、last()
等这些方法能支持第三个参数 condition public Children eq(boolean condition, R column, Object val) {}
condition
是一个布尔值,当condition
为false
时,当前这个条件方法不会生效,即生成的 sql 不会拼接这个条件;所以在这个参数里判断查询参数是否为空即可。
List<User> list = userService.lambdaQuery()
.eq(phone != null && !"".equals(phone), User::getName, name).list();
MP mapper 层 lambda 查询
为了避免我们在代码中写类似的于user_name
的硬编码 Lambda 的好处是降低代码的耦合性,不需要把字段名写死。
List<User > users = userMapper.selectList(new QueryWrapper<User>().eq("user_name", id));
// 替换成下面的
List<User> user=userMapper.selectList(new QueryWrapper<User>().lambda().eq(User::getuserName, userName));
MP 分页条件查询
Page<User> pageInfo = userService.lambdaQuery()
.eq(name != null && !"".equals(name), User::getName, name)
.eq(phone != null && !"".equals(phone), User::getPhone, phone)
.page(new Page<>(pageNum, pageSize));
MP 查询指定字段
Page<User> pageInfo = userService.lambdaQuery()
.select(User::getId, User::getName, User::getPhone)
.eq(name != null && !"".equals(name), User::getName, name)
.eq(phone != null && !"".equals(phone), User::getPhone, phone)
.page(new Page<>(pageNum, pageSize));
// 查询出的实体类中的其他字段为null
MP or()
用法
UserService.lambdaQuery()
.eq(User::getUnionid, unionid).eq(User::getWxAppid, 1)
.or()
.eq(User::getUnionid, unionid).eq(User::getWxAppid, 2)
.list();
MP 去重查询
List<DetectHistory> lineNameList = detectHistoryService.query().select("distinct line_name").list();
MP lambdaQuery 查询实体过滤成指定字段
List<String> companyNameList = companyService.lambdaQuery().select(Company::getName).list().stream().map(Company::getName).collect(Collectors.toList());
MySQL 索引长度超过 767 bytes 问题
Specified key was too long; max key length is 767 bytes 设置 MySQL 的全局参数innodb_large_prefix=ON
,将 InnoDB 表的索引长度上限扩大到 3072 个字节。
MP 解决分页不生效
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
实体类 boolean 类型字段数据库转换问题
实体类is_delete
类型为boolean
, 对应数据库中的int
类型时, 如果实体类不传参, 数据库中的is_delete
字段接收不到值就默认为 0, 就算数据库中设置is_delete
字段默认值为 1, 不传参也是为 0,故boolean
类型必须得传值。
MyBatis 中 in 查询
使用 Java 8 的String.join()
方法将整数列表转换为逗号分隔的字符串,然后将其传递给查询。以下是一个示例代码:
@Select("SELECT ceramic_id FROM detect_history WHERE device_id IN (${deviceIds})")
List<String> listByField(@Param("deviceIds") List<Integer> deviceIds);
// 调用方法
List<Integer> deviceIds = Arrays.asList(1, 2, 3);
String deviceIdsStr = String.join(",", deviceIds.stream().map(Object::toString).collect(Collectors.toList()));
List<String> result = listByField(deviceIdsStr);
多条件排序查询优先级
SELECT * FROM user ORDER BY age DESC, id ASC
优先降序age,再升序id
MP 只查表字段中的一列
List<Integer> companyDeviceIds = companyDeviceService.lambdaQuery()
.eq(CompanyDevice::getCompanyId, companyId).list()
.stream().map(CompanyDevice::getDeviceId)
.collect(Collectors.toList());
动态SQL
注解 SQL:
@Select("SELECT name FROM info WHERE id = #{id}")
String selectName(int id); //静态SQL
@Select("<script> SELECT name FROM info WHERE id = #{id}
<if test= "id != null and id != '' "> and type = 1 </if> </script>")
String selectName(int id); //动态SQL
类 SQL:
@SelectProvider(type = staticProvider.class, method = "selectName")
String selectName(int id); //静态SQL
public class staticProvider{
public String selectName(int id){
return new SQL().SELECT(name).FROM(info).WHERE("id = #{id}").toString();}
}
@SelectProvider(type = dynamicProvider.class, method = "selectName")
String selectName(int id); //动态SQL
public class dynamicProvider{
public String selectName(int id){
StringBuilder where = new StringBuilder();
return new SQL(){
SELECT("name");
FROM("info");
WHERE("id = #{id}");
if(id !=null && id.equals("")){
where.append("and type = 1")
WHERE(where.toString());}
}.toString();
}
}
XML SQL:
String selectName(int id); //静态SQL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.luxiaolan.oral.mapper.Mapper">
<select id = "selectName" resultType="java.lang.String">
SELECT name FROM info WHERE id = #{id}
</select>
</mapper>
String selectName(int id); //动态SQL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.luxiaolan.oral.mapper.Mapper">
<select id = "selectName" resultType="java.lang.String">
SELECT name FROM info WHERE id = #{id}
<if test="id !=null and id !='' ">
and type = 1
</if>
</select>
</mapper>