MyBatis动态SQL详解
https://blog.csdn.net/SGLP521/article/details/121509714
MyBatis Plus 代码生成器3.5.1 相关配置
https://blog.csdn.net/qq_41726758/article/details/120117374
https://blog.csdn.net/weixin_46549023/article/details/128684304
1
1
SpringBoot单元测试Mybatis的DAO层
添加spring-boot-starter-test依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
创建测试类
@RunWith(SpringRunner.class) 指定当前运行环境
@SpringBootTest 指定当前类是一个测试类,classes属性指定启动类
@Test 指定当前方法是一个单元测试方法
AppTest.java
@RunWith(SpringRunner.class)
@SpringBootTest(classes= {App.class})
public class AppTest {
@Autowired private DeptDao deptDao;
@Test
public void test0() {
assert deptDao != null;
System.out.println(deptDao.queryDepts("市场部", 0, 10)); //分页查询
}
@Test
public void test1() {
Dept dept = new Dept();
for(int i=1033;i<=1042;i++) {
dept.setId(""+i);
dept.setName("dept"+i);
dept.setLevel(1);
deptDao.addDept(dept);
}
}
Mybatis持久层
引入mybatis.cfg.xml 文件
application.properties
#当前数据源类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#数据库驱动程序、连接地址、用户名、密码
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
# 连接池设置:初始连接数、最小、最大连接数、最大超时时间
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=6000
# druid监听过滤配置
spring.datasource.druid.filters=stat,wall,log4j
# 配置 Mybatis
mybatis.configuration-location=classpath:mybatis.cfg.xml
#定义所有操作类的别名所在包
mybatis.type-aliases-package=com.example
#所有mapper映射文件
mybatis.mapperLocations=classpath:mapper/*.xml
# 开启驼峰uName自动映射到u_name
#mybatis.map-underscore-to-camel-case: true
DeptDao.java
package com.example.demo;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface DeptDao {
public List<Dept> queryDepts(@Param("name") String name, @Param("currentPage") int currPage, @Param("pageSize") int pageSize);
public boolean addDept(Dept dept);
public Dept queryDeptById(String id);
public boolean update(Dept dept);
}
DeptDao.xml
路径 src\main\resource\mapper\DeptDao.xml
<?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.example.demo.DeptDao">
<select id="queryDepts" resultType="Dept">
<!-- SELECT * FROM dept where name like '%${name}%'; -->
SELECT * FROM dept where 1=1
<if test="name != null and name != '' ">
AND name = #{name, jdbcType = VARCHAR}
</if>
limit #{currentPage} , #{pageSize}
</select>
<select id="queryDeptById" parameterType="java.lang.String" resultType="Dept">
SELECT * FROM dept WHERE id=#{id}
</select>
<insert id="addDept" parameterType="Dept">
insert into dept(id, name, level) values(#{id}, #{name}, #{level});
</insert>
<update id="update" parameterType="Dept">
update dept set name=#{name}, level=#{level} where id=#{id}
</update>
</mapper>
MyBatis分页查询一次同时返回总数和数据
https://blog.csdn.net/qgnczmnmn/article/details/101298599
设置允许sql进行多语句执行:allowMultiQueries=true
SELECT SQL_CALC_FOUND_ROWS * FROM cm_user LIMIT page, pageSize;//带分号
SELECT FOUND_ROWS() AS total;
Mybatis 参数详情
insertSelective和insert的区别?
1、selective的意思是:选择性
2、insertSelective--选择性保存数据(通俗点儿就是说你需要什么字段,他就会对应的插入哪个字段); 比如User里面有三个字段:id,name,age,password 但是我只设置了一个字段; User u=new user(); u.setName("张三"); insertSelective(u);
3、insertSelective执行对应的sql语句的时候,只插入对应的name字段;(主键是自动添加的,默认插入为空) insert into tb_user (id,name) value (null,"张三");
4、而insert则是不论你设置多少个字段,统一都要添加一遍,不论你设置几个字段,即使是一个。 User u=new user(); u.setName("张三"); insertSelective(u); insert into tb_user (id,name,age,password) value (null,"张三",null,null);
原文链接:https://blog.csdn.net/lala12d/article/details/81230930
resultType 与 resultMap
一、若查询语句中配置的是resultType=“实体类/DTO” ,则从mybatis返回的键值对结果集(Map)会直接赋值给该DTO(根据set()/get()方法,因此该DTO属性名要与表字段名一致,若不一致,可再sql查询语句中用as 更换查出来表字段名)中相映射的属性值,而与该mappper.xml文件配置< mapper/>里的< resultMap />无关。
二、若查询语句中配置的是resultMap=“< mapper/>中配置的< resultMap />”,则从mybatis返回的键值对结果集(Map)会根据该< resultMap />配置中(column-property)的相应属性赋值。
resultMap是Mybatis最强大的元素,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中。
https://www.cnblogs.com/kenhome/p/7764398.html
MyBatis ofType和javaType区别
JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型。
参考地址:https://blog.csdn.net/u013216156/article/details/78642920
useGeneratedKeys=“true”
Mybatis 配置文件 Mapper参数 useGeneratedKeys=“true” keyProperty=“id”
useGeneratedKeys设置为 true 时,表示如果插入的表id以自增列为主键,则允许 JDBC 支持自动生成主键,并可将自动生成的主键id返回。
useGeneratedKeys参数只针对 insert 语句生效,默认为 false;
<insert id="saveDevBmsState" useGeneratedKeys="true" keyProperty="state.id" keyColumn="id">
INSERT INTO cm_information_state(dev_id, signals, update_time)
VALUES(#{state.electric}, #{state.signals}, UNIX_TIMESTAMP(now()));
</insert>
MyBatis中开启查询缓存及flushCache与useCache的使用
https://blog.csdn.net/u014749862/article/details/80297943
Mybatis省略@Param注解操作
https://www.freesion.com/article/30181507007/
mybatis显示sql日志
实体类与字段不一致读取为null
方法1:在查询中含有表字段与对象字段不对应的,可以在查询语句用as 对象字段名解决字段不一致不自动封装的问题
方法2:修改select元素中resultType属性 为 resultMap属性并创建返回的map类型
Mybatis框架实体类字段与数据库表字段不一致导致查询该字段的值一直为null
https://blog.csdn.net/qq_34332010/article/details/77151860
提取< where > < if >共用代码
mybatis提取< where >< if >共用代码
https://www.cnblogs.com/EnzoDin/p/6445281.html
sql语句输入小于号出错
在mybatis中sql是写在xml映射文件中的,如果sql中有一些特殊字符的话,在解析xml文件的时候就会被转义。
改为 <
where id='1001' and now()-create_time < 300
https://blog.csdn.net/qq_43153693/article/details/90674017
#号与$符号
根据MyBatis官方文档的解释:
默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并安全地设置值(比如?)。这样做更安全,更迅速,通常也是首选做法。
有时你只是想直接在 SQL 语句中插入一个字符串,比如 ORDER BY,你可以使用:ORDER BY ${columnName}
。这里 MyBatis 不会修改或转义字符串。
以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。
我们可以这样理解:
使用#{参数}格式的语法在myBatis中是使用预处理语句Preparement语句来进行设置值的,类似于:
PreparedStatement ps = conn. prepareStatement(sql);
ps.setInt(1,id);
Ps.setString(2,userName);
这种方式,MyBatis不会修改或者转义字符串。
${columnName}
相当于:
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery(sql);
相比而言:
#{},更加安全,能够防范SQL注入;
${},无法防范SQL注入,一般用于传入不需要转义的参数。
MyBatis forEach List操作
DAO内容
List<RentReturnRate> queryRentReturnRateList(List<Integer> memberIds, Integer page, Integer pageSize);
xml文件内容:
<select id="queryRentReturnRateList" resultMap="rentReturnRate">
SELECT * FROM cm_rent_return_rate
WHERE 1=1
<if test="memberIds != null and memberIds.size >0">
and member_id in
<foreach collection="memberIds" item="memberIds" open="(" separator="," close=")">
#{memberIds}
</foreach>
</if>
ORDER BY area_code
LIMIT #{page}, #{pageSize}
</select>
其他
IDEA编译后没有找到mapper.xml文件
Component中的DAO mapper没有实例化
No qualifying bean of type ‘cn.lishe.StateDao’ available: expected at
least 1 bean which qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
解决:检查maven编译的时候没有将xml文件build到target目录中
2019-11-15 10:44:22.812 WARN 6364 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'stateHandler': Unsatisfied dependency expressed through field 'stateDao';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cn.lishe.StateDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Mapper参数 报错There is no getter for property named xxx
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘state’ in ‘class cn.wxtong.State’
Mapper Dao修改:
//保存一条数据(实体类)添加参数
public void saveState(@Param("state")State state);
@Mapper为什么可以不用写
也可以在mybatis配置类写@MapperScan({“com.mallplus.order.mapper*”}),在这个配置文件中就已经指定mapper的扫描地址
OGNL
在这儿所有的看到这篇文章的老铁们,注意咯,MyBatis 在编写动态SQL的时候,是基于OGNL的,只要记住这一点,你就一定不会错了,至于什么 OGNL,OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言,OGNL为什么这么受欢迎呢,原因很简单,它相对其它表达式语言具有下面几大优势:
1、基本对象树的访问;
2、对容器变量的访问;
3、使用操作符号;
4、容器、数组、对象;
5、对静态方法或变量的访问;
6、方法调用;
7、投影和选择;
链接:https://blog.csdn.net/Hello_World_QWP/article/details/86513179
资料
SpringBoot整合Mybatis+PageHelper分页实现增删查改
https://blog.csdn.net/weixin_36279318/article/details/82776632
SpringBoot整合Mybatis实现自动转换枚举类型
https://blog.csdn.net/qq_26440803/article/details/83451221
如何设计一个本地缓存
https://mp.weixin.qq.com/s/f9c2LVa5LxzMSj9C01Fn_Q