特点:轻量级,灵活,简单易学,效率高
mapper: namespace接口名称 id接口方法名、 parameterType接口参数类型 resultType接口返回值类型
导入mapper文件的方式:< mapper resource=“”/>
< mapper class=“”/>
< package name=“”/>
SqlSessionFactoryBuilder:方法级,用来创建session工厂和读取配置文件
SqlSessionFactory:项目级,用来创建会话
SqlSession:线程级,用来执行sql操作
MyBatis配置文件规定了标签的顺序,打乱了顺序就会出错:
configuration property settings typeAliases typeHandlers objectFactory plugins environments databaseIdProvider mappers
一对一: javaType:java数据类型
使用一对一查询时,在一个实体类中添加另一实体类属性。用resultMap实现映射关系时,使用association连接,javaType为封装的类型。
使用association处理映射关系
<resultMap id="empAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid">id>
<result property="empName" column="emp_name">result>
<result property="age" column="age">result>
<result property="sex" column="sex">result>
<result property="email" column="email">result>
<association property="dept" javaType="Dept">
<id property="did" column="did">id>
<result property="deptName" column="dept_name">result>
association>
resultMap>
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
select>
一对多: Property:实体类中的属性 Column:数据库字段名 select:二次查询
一对多是在一个类中包含另一个类list的集合,在映射时,使用Collection,ofType为封装类型。注意封装类型与一对一不同
public class Dept{
private Integer did;
private String deptName;
private List<Emp> emps;
}
collection
collection:用来处理一对多的映射关系
ofType:标识该属性对应的集合中存储的数据的类型
<resultMap id="DeptAndEmpResultMap" type="Dept">
<id property="did" column="did">id>
<result property="deptName" column="dept_name">result>
<collection property="emps" ofType="Emp">
<id property="eid" column="eid">id>
<result property="empName" column="emp_name">result>
<result property="age" column="age">result>
<result property="sex" column="sex">result>
<result property="email" column="email">result>
collection>
resultMap>
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
select>
多对多:
表之间的多对多关系稍微复杂,需要一个中间表来表示
中间表有三个字段,其中两个字段分别作为外键指向各自一方的主键,由此通过中间表来表示多对多关系,通过一个表联合另一个中间表可以表示为一对多关系。
多对多,其实可以从一方到另一方表示为一对多关系,反之亦然
student_role_tb : id,studentid, roieid
如:查找职位,并包含对应的学生信息,一个职位可能有很多学生,如组长,一对多关系
第一步: 在role实体中添加student属性,
第二步:书写映射关系,按一对多即可
<resultMap id="roleWithStudent" type="Role">
<id property="roleid" column="roleid">id>
<result property="rolename" column="rolename">result>
<collection property="studentList" column="studentid" ofType="Student">
<id column="id" property="id">id>
<result property="name" column="name">result>
<result property="age" column="age">result>
<result property="sex" column="sex">result>
<result property="height" column="height">result>
<result property="sAddress" column="s_address">result>
collection>
resultMap>
<select id="findAllRoleWithStudent" resultMap="roleWithStudent">
select r.*,sr.studentid, s.* from role_tb r LEFT JOIN student_role_tb sr on r.roleid=sr.roleid
LEFT JOIN student_tb s on s.id = sr.studentid
select>
反之亦然,如:查找学生并包含职位信息,也是一对多关系
第一步: 在student实体中添加role属性,
第二步:书写映射关系,按一对多即可
<resultMap id="studentWithRole" type="Student">
<id property="id" column="id">id>
<result property="name" column="name">result>
<result property="age" column="age">result>
<result property="sex" column="sex">result>
<result property="height" column="height">result>
<result property="sAddress" column="s_address">result>
<collection property="roleList" column="roleid" ofType="Role">
<id property="roleid" column="roleid">id>
<result property="rolename" column="rolename">result>
collection>
resultMap>
<select id="findAllStudentWithRole" resultMap="studentWithRole">
select s.*,sr.studentid, r.* from student_tb s LEFT JOIN student_role_tb sr on s.id = sr.studentid
LEFT JOIN role_tb r on r.roleid = sr.roleid;
select>
延迟加载、立即加载:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
@Test
public void getEmpAndDDeptByStepOne(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp =mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName());
}
@Test
public void getEmpAndDeptByStepOne() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = mapper.getEmpAndDeptByStepOne(1);
System.out.println(emp.getEmpName());
System.out.println("----------------");
System.out.println(emp.getDept());
}
fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy|(延迟加载)|eager(立即加载)"
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id property="eid" column="eid">id>
<result property="empName" column="emp_name">result>
<result property="age" column="age">result>
<result property="sex" column="sex">result>
<result property="email" column="email">result>
<association property="dept"
select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="did"
fetchType="lazy">association>
resultMap>
一级缓存失效:
在应用运行过程中,当多次执行查询条件完全相同的SQL,会优先命中一级缓存,避免直接对数据库进行查询,提高性能
使一级缓存失效的四种情况:
不同的SqlSession对应不同的一级缓存
同一个SqlSession但是查询条件不同
同一个SqlSession两次查询期间执行了任何一次增删改操作
同一个SqlSession两次查询期间手动清空了缓存
二级缓存:
二级缓存被多个SqlSession共享,是一个全局的变量。(二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取)
二级缓存开启的条件
1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
2. 在映射文件中设置标签
3. 二级缓存必须在SqlSession关闭或提交之后有效
4. 查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
特点:一站式、轻量级、方便解耦
IOC(控制反转):IOC构建bean对象时的不同作用域(scope属性) Singleton(默认) prototype request session globalsession
DI(依赖注入):set注入、构造注入、接口注入(不提倡)
1.set方法注入
在UserServiceImpl中添加setUserDao方法
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
配置Spring容器调用set方法进行注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
bean>
P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:
首先,需要引入P命名空间:
xmlns:p="http://www.springframework.org/schema/p"
其次:需要修改注入方式
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
2.构造方法注入
创建有参构造
public class UserServiceImpl implements UserService {
@Override
public void save() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) applicationContext.getBean("userDao");
userDao.save();
}
}
配置Spring容器调用有参构造时注入
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao">constructor-arg>
bean>
AOP:
面向切面编程、动态代理
AOP编程的支持:通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。
通知、连接点、切点、切面、引入、织入
连接点是在应用执行过程中能够插入切面(Aspect)的一个点。这些点可以是调用方法时、甚至修改一个字段时。
切入点是一些特使的连接点,是具体附加通知的地方。
切面是通知和切入点的结合,通知规定了在什么时机干什么事,切入点规定了在什么地方。
引入:允许我们向现有的类添加新方法属性。
把切面应用到目标对象并创建代理对象的过程。切点在指定的连接点(切点)被织入到目标对象中。在目标的生命周期中,有多个点可以被织入:编译期、类加载期、运行期
通知定义了何时,做什么。
通知的种类和定义
后置通知、返回通知、异常通知、环绕通知、前置通知。
Aop的5种增强方法:https://blog.csdn.net/qq_51649461/article/details/119850190
before,after,after-throwing,after-returning,around
自动代理的方式使用aop,需要在配置文件中开启autoproxy
生命式事务管理:spring采用AOP的方式实现
springMVC执行的过程
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找 Handler
可以根据xml配置、注解进行查找
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
ModelAndView是springmvc框架的一个底层对象,包括 Model和view
第八步:前端控制器请求视图解析器去进行视图解析
根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染
视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果
注解:书p142
@RequestParam 默认required=true
@ResponseBody:修改响应体,利用此特性可以返回json
@RequestMapping :请求URL和处理方法之间的对应关系
@PathVariable:解析url中的占位符
文件上传:maxUploadSize defaultEncoding enctype=“multipart/form-data”
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000000" />
<property name="defaultEncoding" value="utf-8" />
bean>
多文件上传,只需要将页面修改为多个文件上传项,将方法参数MultipartFile类型修改为MultipartFile[]即可
<h1>多文件上传测试h1>
<form action="${pageContext.request.contextPath}/quick21" method="post" enctype="multipart/form-data">
名称:<input type="text" name="name"><br>
文件1:<input type="file" name="uploadFiles"><br>
文件2:<input type="file" name="uploadFiles"><br>
文件3:<input type="file" name="uploadFiles"><br>
<input type="submit" value="提交"><br>
form>
@RequestMapping("/quick21")
@ResponseBody
public void quickMethod21(String name,MultipartFile[] uploadFiles) throws IOException {
for (MultipartFile uploadFile : uploadFiles){
String originalFilename = uploadFile.getOriginalFilename();
uploadFile.transferTo(new File("C:\\upload\\"+originalFilename));
}
}
返回值类型:String、void、ModelAndView
配置文件:
拦截器的配置、前端控制器的配置、视图解析器的配置、文件上传下载配置
dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
dispatcherServlet
/
Springmvc的spring容器由监听器启动,启动时启用webApplicationContext对象
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:applicationContext.xml
环境搭建:web.xml、applicationContext.xml、springMVC.xml
代码编写:测试SSM整合