day 1 2021.10.1
JavaSE 反射
JavaSE 注解
day 2 2021.10.2 - 10.7
SSM
filter
spring 事务处理(增强)
tx 是事务注解生效
String builder
String buffer
🔣服务器接收json,要在 形参前+ @RequestBody 来接收
springMVC
json数据的请求响应处理
地址栏,form表单的数据请求响应处理
小结
1、MyBatis 代理模式和普通模式的区别
1.1、mapper中的xml文件,
代理模式
普通模式 只要和Test类中执行sql语句时引用时一致即可。
resultType:返回的结果类型,如果时查询,那么返回的一定是对应的bean类型
parameterType:参数类型 ,根据实际情况使用,填写,有就填相对应的,反之default
1.2、测试Test时
1.2.1、相同点
- 获取核心配置文件:
InputStream stream = Resources.getResourceAsStream(" SqlMapConfig.xml")
- 获取工厂:
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBiluder().build( stream)
- 获取连接:
SqlSession sqlSession = sqlSessionFactory.openSession();
1.2.2、不同点
不使用代理模式,执行sql语句是:
List<User> list = sqlSession.selectList("userMapper.findAll");
代理模式下:首先创建接口的代理mapper对象
类名Mapper mapper = sqlSession.getMapper(反射类名.class)
mapper调用接口中的方法去执行sql语句
1.3、使用代理模式的优点
可以像之前那样,在service层可以面向接口编程,不使用代理模式由于没有接口所以不能。
1.4、插件 free MyBates plugin 生成mapper映射文件的
2、注意
prom中build 路径是"/" mapper.xml中路径是"." ,有提示就对了
接口方法中,单个参数时,xml映射文件中,属性值的时候,使用#{bena属性}
多个参数时
要使用序号参数绑定 :#{arg0} #{arg1}, 与 #{param1},#{param2},效果一样。
官方推荐注解参数模式绑定:在接口方法参数列表中**@param(“这里的名字和xml中属性一致”)**
使用map作为参数绑定:在接口方法中参数为Map map集合对象,xml中属性要与map中的key值一致。测试的时候,创建map对象,根据sql语句增加相对应的属性,进行便利查询。
使用对象作为参数绑定:在接口方法中参数为bean对象,xml中属性要与bean中的属性名一致。
模糊查询
like concat(‘%’ tom ‘%’) 模糊操作sql中 xxx中包含tom的
_ : 表示一个字符
% : 表示0个或多个字符
主键回填:通过last_insert_id()函数查询主键
就是把获取主键值value赋值给bean中的主键属性property
<insert id="add" parameterType="user">
keyColumn:sql表中相对应主键列名
keyProperty:bean中对象的属性名
resultType:获取主键返回类型,同bean和sql中的一致
order:获取主键是在什么时候获取,before表示sql语句执行前获取,after表示sql语句执行后获取,根据实际情况选择。
<selectKey keyColumn="id" keyProperty="id" resultType="long" order="AFTER">
<!-- 适用于整数类型自增主键 -->
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username, password, age, gender, addr) values(#{username}, #{password}, #{age}, #{gender}, #{addr})
</insert>
动态SQL语句 trim
接口: List<User> findByConditon(User user);
XML:
<select id="findByCondition" resultType="User" parameterType = "User">
select * from
<trim prefix = "where" prefixOverrides="and|or"> <!--还有一种写法 suffixOverrides=","表示自动省略最后一个","号 -->
<if test="username != null">
and username = #{username}
</if>
<if test="age != null">
and age = #{age}
</if>
<if tesst="addr != null">
and addr = #{addr}
</if>
</trim>
</select>
<!-- 如果是Update修改,<trim替换的是set prefix="set" suffixOverrides=",">
Condition语句没有and|or, 每条Condition语句用","分隔 -->
动态SQL语句foreach
foreach用来循环执行sql的拼接操作,例如:SELECT * FROM user WHERE id IN (1,2,3)。
<select id="findByIds" resultType="user">
SELECT * from user
<where>
<!--
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
-->
<foreach collection="list" open="id in (" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
对应的Mapper接口
List<User> findByIds(List<Integer> ids);
测试方法
@Test
public void testFindByIds() {
List<Integer> ids = Arrays.asList(1,2,3,4);//这里Arrays.aslist()方法可以放N个参数,不用new
List<User> list = userMapper.findByIds(ids);
list.forEach(u -> System.out.println(u));
}
SQL代码片段抽取
<sql id="select1"> <!-- 定义sql标签,抽取片段select1-->
SELECT * FROM user
</sql>
<select id="findByCondition" resultType="user">
<include refid="select1" /> <!-- 引用抽取片段select1-->
</select>
注意多表查询中【一对多】和【一对一】语法上的区别
【多表查询和单表查询区别】需要定义一个resultMap
【一对一】:<association property="bean中的属性名" javaType = "bean" > </association>
【一对多】:<collection property="bean中的属性名" ofType = "bean " ></collection>
一对一查询 两种方式
准备、
- 数据库2个表
- 配置环境
- bean 2个
- mapper 2个接口,2个xml
多表查询,以前的resultType就不能用了,要换成,resultMap,但是要提前声明,resultMap
<!--
resultMap:完成结果映射,表的字段到对象属性的映射,在表的字段名和对象属性名不相同时通常会被用到-->
<!--第一种声明resultMap的方式-->
<resultMap id="orderMap" type="order">
<!-- id:设置主键列的对应关系 column:表的字段名 property:对象的属性名-->
<id column="id" property="id" />
<!-- result:设置普通列的对应关系 column:表的字段名 property:对象的属性名 -->
<result column="ordertime" property="ordertime" />
<result column="total" property="total" />
<result column="uid" property="user.id" />
<result column="username" property="user.username" />
<result column="password" property="user.password" />
</resultMap>
<!--第二种声明resultMap的方式-->
<resultMap id="orderMap" type="order">
<id column="id" property="id" />
<result column="ordertime" property="ordertime" />
<result column="total" property="total" />
<!--
association:用于建立一对一的关系
javaType:指定属性的类型
-->
<association property="user" javaType="user">
<id column="uid" property="id" />
<result column="username" property="username" />
<result column="password" property="password" />
</association>
</resultMap>
<!--
resultMap:用于指定要使用的resultMap
-->
<select id="findAll" resultMap="orderMap">
SELECT
o.*, u.id uid, u.username username, u.password password
FROM
`order` o, user u
WHERE
o.uid=u.id;
</select>
多对多(三张表)
多对多,其实就是双向的一对多
增加第三张表,表示关联关系
把多的一方,集合放在少的一方,声明全局变量
PS:如果要利用之前的项目进行修改,步骤:复制的项目包,要保留src和prom其他删除,在prom中修改该项目名称即可。
3、PageHelper 分页查询
MyBatis可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封装,使用简单的方式即可获得分页的相关数据。
开发步骤:
在pom.xml中添加相关依赖;
在核心配置文件配置PageHelper插件;
测试。
3.1、在pom.xml中添加相关依赖
<!-- 分页助手 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
3.2、在核心配置文件配置PageHelper插件
<!-- 配置插件 -->
<plugins>
<!-- 配置分页插件 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 配置分页插件方言 -->
<property name="dialect" value="mysql" />
</plugin>
</plugins>
3.3、测试
@Test
public void test3() {
PageHelper.startPage(2, 2);
List<User> users = userMapper.findAll();
users.forEach(item -> System.out.println(item));
PageInfo<Student> pageInfo = new PageInfo<>(users);
System.out.println("总记录数:" + pageInfo.getTotal());
System.out.println("当前页:" + pageInfo.getPageNum());
System.out.println("总页数:" + pageInfo.getPages());
System.out.println("上一页:" + pageInfo.getPrePage());
System.out.println("下一页:" + pageInfo.getNextPage());
System.out.println("是否是首页:" + pageInfo.isIsFirstPage());
System.out.println("是否是尾页:" + pageInfo.isIsLastPage());
}
4、缓存
浏览器> Nginx(缓存集群)>web应用>Redis(缓存集群)>数据库(多份)
报错
找不到方法看这里
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): org.example.mapper.UserMapper.findAll
- mapperxml看下
<!--namespace全类名和接口是否一样,"."不要"/"-->
<?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="org.example.mapper.UserMapper"><!--namespace地址间隔"."不要"/"-->
- prom里看一下bulid设置
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
jdbc.properties四大参数报错看这里
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatistest?useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root
jdbc配置文件错误之一:
org.apache.ibatis.exceptions.PersistenceException:
Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
The error may exist in org/example/mapper/UserMapper.xml
The error may involve org.example.mapper.UserMapper.findAll
The error occurred while executing a query
Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
解决办法:去找jdbc.properties中的错误
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost3306/mybatistest?useSSL=false&useUnicode=true&characterEncpding=utf8
/**上面的localhost少个":"号*/
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatistest?useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root