mybatis:
特点:轻量级,灵活,简单易学,效率高
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处理映射关系
- association:处理多对一的映射关系
- property:需要处理多对一的映射关系的属性名
- javaType:该属性的类型
<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>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<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>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<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>
<!--property role表中的属性-->
<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>
延迟加载、立即加载:
- 分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
- lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有的关联对象都会延迟加载
- aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性都会按需加载。(默认为false)
- 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy|eager(立即加载)”
<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());
}
- 关闭延迟加载,两条语句都会执行
- 开启延迟加载,只运行获取emp的SQL语句
@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());
}
- 开启后,需要用到查询dept的时候才会调用相应的SQL语句
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. 在映射文件中设置标签<cache />
3. 二级缓存必须在SqlSession关闭或提交之后有效
4. 查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
spring
特点:一站式、轻量级、方便解耦
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
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">
<!-- 设置上传文件的大小 100M,如果同时传多个文件,则是所有文件的大小 -->
<property name="maxUploadSize" value="100000000" />
<!-- 字符编码的设置,默认是ISO-8859 -->
<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
配置文件:
拦截器的配置、前端控制器的配置、视图解析器的配置、文件上传下载配置
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" propagation="SUPPORTS" read-only="true" isolation="DEFAULT"/>
<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.swpu.service.*.*(..))"/>
</aop:config>
<!-- 前端控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 开启spring注解扫描-->
<context:component-scan base-package="com.swpu"></context:component-scan>
<!-- 开启springMVC注解扫描-->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 文件上传的多部分解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的大小 100M,如果同时传多个文件,则是所有文件的大小 -->
<property name="maxUploadSize" value="100000000" />
<!-- 字符编码的设置,默认是ISO-8859 -->
<property name="defaultEncoding" value="utf-8" />
</bean>
SSM整合:
Springmvc的spring容器由监听器启动,启动时启用webApplicationContext对象
<!-- spring监听器:-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
环境搭建:web.xml、applicationContext.xml、springMVC.xml
代码编写:测试SSM整合