2022 5/31
前序学习 javaSE-> MySQL-> JDBC -> ->AJAX
代理模式
1.代理模式的作用
1)控制目标对象的访问
2)增强功能
2.代理模式的分类
1)静态代理
2)动态代理,又分为JDK动态代理,CGLib动态代理(子类代理)
静态代理
什么是静态代理
它是代理模式的一种.
它具备以下特点:
1)目标对象和代理对象实现同一个业务接口
2)目标对象必须实现接口
3)代理对象在程序运行前就已经存在
4)能够灵活的进行目标对象的切换,却无法进行功能的灵活处理(使用动态代理解决此问题)
动态代理
MyBatis实体类的属性名和数据库列名不一致解决方法汇总
http://wjhsh.net/yif0118-p-14601572.html
1.1.查询的sql语句中使用别名进行查询(dnp
1.2.使用resultMap映射实体
<!--
查询全部图书
List<Book> getAll();
实体类
private Integer id;
private String name;
字段的名称和实体类的属性名不一致
方案一:起别名
-->
<!-- <select id="getAll" resultType="book" >
select bookid id ,bookname name
from book
</select>-->
<!--
方案二
resultMap="bookmap"
-->
<resultMap id="bookmap" type="book">
<!--主键绑定-->
<id property="id" column="bookid"></id>
<!--非主键绑定-->
<result property="name" column="bookname"></result>
</resultMap>
<select id="getAll" resultMap="bookmap">
select bookid ,bookname
from book
</select>
1.3.开启SpringBoot-Mybatis驼峰命令配置(默认是开启的)
瑞吉外卖中提到过!!!
一个表 address_book ——> AddressBook
或者某个字段 user_name ——> userName
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射 map-underscore-to-camel-case: true
1.4 mp特有 @TableField()
mybatis返回主键ID
- 设置< insert >便签的属性 设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了(在fortune项目中用到)
- 看一下图片
mybatisplus insert后会自动返回
记录一下mybatis主要知识点
1. 关于parameterType和resultType
- 参数超过一个\集合\数组\简单类型 不用写parameterType 实体类必须写
- 增删改不用写resulttype
-
resultType: 指定查询返回的结果集的类型,如果是集合,必须带泛型 在这里决定了返回的类型
- 实体类你可以写小驼峰是因为注册了别名
<typeAliases>
<!--单个实体类别名的注册-->
<!-- <typeAlias type="com.bjpowernode.bean.Student" alias="student"></typeAlias>-->
<!--批量注册别名
1.主要用这种 它可以批量注册一个包下的所有类
2.别名是类名的小驼峰 StudentOne是studentOne
-->
<package name="com.bjpowernode.bean"/>
</typeAliases>
而使用了spring boot的mybatisplus/mybatis也需要自己手动配置
2. 关于#{}和${} 、 @Param注解
2.1#{}占位符
传参大部分使用#{}传参,它的底层使用的是PreparedStatement对象,是安全的数据库访问 ,防止sql注入. #{}里如何写,看parameterType参数的类型 1)如果parameterType的类型是简单类型(8种基本(封装)+String),则#{}里随便写. 2)parameterType的类型是实体类的类型,则#{}里只能是类中成员变量的名称,而且区分大小写.
2.2${}字符串拼接或字符串替换 拼接尽量不用 因为有sql注入的风险
不要用${}来模糊查询 掌握优化后的模糊查询
'%${username}%' concat('%',#{username},'%')
替换:
${columnName}是字符串替换(这辈子唯一闪耀的地方) #{columnValue}是占位 加个注解就能用
<select id="getByNameOrAddress" resultType="users">
select id,username,birthday,sex,address
from users
where ${columnName} like concat('%',#{columnValue},'%') ==>此处使用的是@Param注解里的名称
</select>
2.3 @param注解
1. 多个参数是要写的(事实上多参数可以不写该注解,但处理起来会很麻烦);
不需要用@Param注解与需要用@Param注解的情况_征程123的博客-CSDN博客
3. Mapper的注册(了解)
使用springboot以后 无论是mybatis or plus 都只需要:(1)@MapperScan注解在启动类上或者配置类上 (2)其他的配置(别名、日志、驼峰映射)都在application文件中 真的是从配置地狱中解放了出来
这是mybatis (spring springmvc中同理 )
springboot+mybatis
springboot+MybatisPlus
4.动态SQL(需要熟练掌握)
<sql> <include> 一组 <if><where>一组 <set> <foreach>
4.1<sql>
<!--定义代码片段-->
<sql id="allColumns">
id,username,birthday,sex,address
</sql>
4.2<include> 用来引用<sql>定义的代码片断
4.3<if>
4.4<where>
<where>中的and是条件的拼接 初始条件1=1(永真)
-->
<select id="getByConditions" resultType="users" parameterType="users">
select <include refid="allColumns"></include>
from users
<where>
<if test="userName != null and userName != '' ">
and username like concat('%',#{userName},'%')
</if>
<if test="birthday !=null">
and birthday = #{birthday}
</if>
<if test="sex != null and sex !='' ">
and sex = #{sex}
</if>
<if test="address != null and address !='' ">
and address like concat('%',#{address},'%')
</if>
</where>
</select>
4.5<set>
<!--
有选择的更新
int updateBySet(Users user);
<set>中的逗号不必纠结
-->
<update id="updateBySet" parameterType="users">
update users
<set>
<if test="userName != null and userName != '' ">
username = #{userName},
</if>
<if test="birthday !=null">
birthday= #{birthday},
</if>
<if test="sex != null and sex !='' ">
sex= #{sex},
</if>
<if test="address != null and address !='' ">
address = #{address},
</if>
</set>
where id = #{id}
</update>
4.6<foreach>用来进行循环遍历,完成循环条件查询,批量删除(最常用),批量增加(掌握),批量更新(用的很少
<foreach>参数详解:
collection:用来指定入参的类型,如果是List集合,则为list,如果是Map集合,则为map,如果是数组,则为array.
item:每次循环遍历出来的值或对象 就是foreach中的item
separator:多个值或对象或语句之间的分隔符
open:整个循环外面的前括号
close:整个循环外面的后括号
<!--
批量删除
int deleteBatch(Integer[] id);
-->
<delete id="deleteBatch" >
delete from users
where id in
<foreach collection="array" separator="," item="id" open="(" close=")">
#{id}
</foreach>
</delete>
<!--
批量增加
int insertBatch(List<Users> list);
private Integer id;
private String userName;
private Date birthday;
private String sex;
private String address;
思考一下这里的括号 open close
parameterType是不必要的
-->
<insert id="insertBatch" >
insert into users
(username,birthday,sex,address)
values
<foreach collection="list" item="u" separator=",">
(#{u.userName},#{u.birthday},#{u.sex},#{u.address})
</foreach>
</insert>
5.关于Map
5.1入参是map(重点掌握)
如果入参超过一个以上,使用map封装查询条件,更有语义,查询条件更明确.
#{这里面要写的就是map的key}
5.2返回值是Map
5.3 返回多行map
6. resultMap
一个作用是映射实体 看上文;
一个是7;
7.关联关系 了解一下 用的不多
(瑞吉中的dto dishdto中有dishflavor的List , 我们只需要用dishflavor的service/mapper再查一边就好了 )
总结:无论是什么关联关系,如果某方持有另一方的集合,则使用<collection>标签完成映射,如果某方持有另一方的对象,则使用<association>标签完成映射。
MP
application.yml
spring:
# 配置数据源信息
datasource:
# 配置数据源类型
type: com.zaxxer.hikari.HikariDataSource
# 配置连接数据库信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
username: root
password: root
#日志
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type:auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#起别名
type-aliases-package: com.atguigu.pojo
mp中生成主键id默认使用的是雪花算法
BaseMapper、Iservice、ServiceImpl
extends 、implement ?
常用注解
1.@TableName
在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表 由此得出结论,MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定
a.问题? 若实体类类型的类名和要操作的表的表名不一致,会出现什么问题?
b>通过@TableName解决问题 在实体类类型上添加@TableName("t_user"),标识实体类对应的表,即可成功执行SQL语句
c>通过全局配置解决问题
global-config: db-config: # 配置MyBatis-Plus操作表的默认前缀 table-prefix: t_
2 @TableId
详细看一下pdf
3.@TableField
a>情况1 若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格 例如实体类属性userName,表中字段user_name 此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格 相当于在MyBatis中配置
b>情况2 若实体类中的属性和表中的字段不满足情况1 例如实体类属性name,表中字段username 此时需要在实体类属性上使用@TableField("username")设置属性所对应的字段名
还可以通过起别名、 resultMap 一共四种方法
4 @TableLogic
>逻辑删除
条件构造器和常用接口
以后查询就用LambdaQueryWrapper
更新就用LambdaUpdateWrapper
带condition的Lambda
@Test
public void test11(){
String username = null;
Integer ageBegin = 10;
Integer ageEnd = 24;
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
lambdaQueryWrapper
.like(username !=null,User::getName,"a")
.ge(ageBegin !=null,User::getAge,ageBegin)
.le(ageEnd != null,User::getAge,ageEnd)
;
userMapper.selectList(lambdaQueryWrapper);
}
分页插件
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
@Configuration
@MapperScan("com.atguigu.Mapper") //添加到这里
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
reggie中的demo
* long current 当前页 从1开始 * long size
/**
* 分页查询
* @return
*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize){
Page<Category> p = new Page<>(page,pageSize);
//根据sort进行排序
LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByAsc(Category::getSort);
categoryService.page(p,lambdaQueryWrapper);
return R.success(p);
}
AND和OR
@Test
/**
* 将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
*/
public void test04(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.gt("age",20) //grand than 大于
.like("name","a")
.or() //链式之间是and
.isNull("email")
;
User user = new User();
user.setEmail("123@qq.com");
userMapper.update(user,queryWrapper);
}
/**
* 和04对比!! 条件的优先级 lamdba优先!!
* 将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
*/
@Test
public void test05(){
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.like("name","a")
/* .and(new Consumer<QueryWrapper<User>>() {
@Override
public void accept(QueryWrapper<User> userQueryWrapper) {
userQueryWrapper.gt("age",20).isNull("email");
}
})*/
.and(i -> i.gt("age",20).or().isNull("email") )
;
User user = new User();
user.setEmail("123567@qq.com");
userMapper.update(user,queryWrapper);
}