spring
轻量级的容器
负责创建 管理 维护bean
IOC
控制反转
控制权的转移
DI:依赖注入
bean的创建和管理
实例化bean:
无参构造方法实例化:
<bean id="" class=""/>
静态工厂方法实例化
工厂类----静态的工厂方法
<bean id="" class="工厂类的类名" factory-method="工厂类中获取bean的静态方法">
非静态工厂方法实例化
工厂类----非静态的方法
定义工厂类的bean
<bean id="" class="工厂类类名"/>
定义bean
<bean id="" factory-bean="" factory-method=""/>
id
scope:
singleton 单例的
prototype 多例的
属性注入:
构造方法注入
<bean id="" class="">
<construntor-arg name="" value=""/>
</bean>
setter方法注入
前提:有属性的set方法
<bean id="" class="">
<property name="" value=""/>
</bean>
注入的是常量值(数值/字符串):
<property name="" value=""/>
注入对象:
<property name="" ref="bean的id">
集合属性注入:
list集合:
<property name="">
<list>
<value></value>
</list>
</property>
set集合:
<property name="">
<set>
<value></value>
</set>
</property>
map映射集合:
<property name="">
<map>
<entry key="" value=""/>
<entry key="" value=""/>
</map>
</property>
<property name="">
<props>
<prop key="">...</prop>
<props>
</property>
上面都是在配置文件中装备bean并实现属性注入
使用注解:
实例化bean的注解:
@Component
描述spring框架中的bean
还提供了和@Component等效的三个增强版的注解:
@Controller 用于对Controller实现类的注解--控制层
@Service 用于对service层实现类的注解----业务层
@Repository 用于对dao层实现类进行注解---持久层
属性注入的注解:
普通属性:
@Value(value="admin")
private String name;
对象属性:
@Autowired 自动装配 默认使用类型注入
@Autowired
@Qualifier("userDao")---按名称注入
等价于
@Resource(name="userDao")
配置bean的范围:
@Scope
实际开发使用xml还是注解?
一般是两种方式结合使用
bean的管理---xml
属性注入----注解
AOP:
面向切面编程
采用横向抽取机制,取代传统纵向继承体系的重复性代码
简单来说,就是将一些通用的功能抽取出来---事务管理 安全检查 性能监视
AspectJ----是一个基于java语言的AOP框架
springAOP引入了对AspectJ的支持
AOP底层原理:
动态代理
spring的AOP代理:
jdk动态代理:对实现了接口的类生成代理
cgLib代理机制:对类生成代理
如果类实现了接口,就是用jdk的动态代理生成代理对象
如果类没有实现任何接口,就使用cglib动态代理生成代理对象
aop的术语:
连接点joinpoint:
就是那些被拦截到的点
在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
切入点pointcut:
是指我们要对那些连接点进行拦截的定义
通知/增强advice:
通知是指拦截到连接点之后要做的事情
通知又分为:
前置通知
后置通知
异常通知
最终通知
环绕通知
引介introduction:
是一种特殊的通知
在不修改的类代码的情况下,可以为运行期的类动态的添加一些方法或者字段
目标对象target:
代理的目标对象
织入:
是指把增强应用到目标对象来创建新的代理对象的过程
代理Proxy:
一个类被AOP织入增强后,就产生一个结果代理类
切面Aspect:是切入点和通知的结合
AOP 的实现:
spring中传统AOP
spring的AspectJ的aop(******)
AspectJ是一个基于java语言的AOP框架
AspectJ表达式:
语法:
execution(表达式)
execution(<访问修饰符> <返回类型><方法名>(<参数>)<异常>)
execution("* com.ytc.dao.*(..)")---检索当前包
execution("* com.ytc.dao..*(..)")--检索包以及当前包的子包
execution("* com.ytc.dao.StudentDao+.*(..)")--检索StudentDao以及子类
AspectJ通知/增强:
@Before 前置通知
在方法之前执行
@AfterReturning 后置通知
在方法之后执行 获取方法返回值
@Around 环绕通知
可以在方法之前和之后来执行,而且可以阻止目标方法的执行
@AfterThrowing 抛出通知
@After 最终通知
不管是否有异常,该通知都会执行
基于注解:
1.导入相应jar包
2.编写被增强类
3.使用Aspectj的注解
@Aspect
public class MyAspect{
@Before("execution(* com.yt.dao.UserDao.add(..))")
public void before(){
.........
}
}
4.配置applicationContext.xml
引入aop约束
<aop:aspectj-autoproxy />--自动生成代理
<bean .../>
基于xml配置:
1.导入jar包
2.编写被增强的类
3.定义切面
public class A{
public void before(){
.........
}
}
4.配置applicationContext.xml
<aop:config>
<!--定义切点-->
<aop:pointcut expression="execution(* com.yt.dao.UserDao.add(..))" id="mypointcut"/>
<aop:aspect ref="">
<!--前置通知-->
<aop:before method="before()" pointcut-ref="mypointcut"/>
</aop:aspect>
</aop:config>
Spring中JdbcTemplate
spring中事务管理:
声明式事务管理—原始方式
1.注册平台事务管理器
2.创建业务层代理对象
声明式事务管理---自动代理 基于切面*******
1.导入包
aspectj
2.在配置文件中引入约束
aop tx
3.注册事务管理器
<bean id="transactionManager" class="...........DataSourceTransactionManager">
<!--注入连接池-->
<propery name="dataSource" ref="">
</bean>
4.事务管理
定义通知---事务
<tx:advice id="txadvice" transaction_manager="transactionManager">
<!--事务属性的配置-->
<tx:attribute>
.....
</tx:attribute>
</tx:advice>
5.aop的配置
<aop:config>
<!--定义切点-->
<aop:pointcut expression="execution(* com.yt.dao.service.*(..))" id="mypointcut"/>
<!--定义切面-->
<aop:advisor advice-ref="txadvice" pointcut_ref="mypointcut"/>
</aop:config>
基于注解:
1.注册事务管理器
<bean id="transactionManager" class="...........DataSourceTransactionManager">
<!--注入连接池-->
<propery name="dataSource" ref="">
</bean>
2.开启注解的事务管理
<tx:annotation-driven transaction_manager="transactionManager"/>
3.在需要开启事务的service上使用注解
@Transactional
注解中有属性值:
isolation
propagation
readonly
......
IOC
AOP
IOC
DI
IOC和DI
AOP
动态代理:是在静态代理模式改进的基础上,动态的创建代理类,使用JavaSE JDK中的proxy类在程序运行时创建代理类,并产生代理对象.
SpringMVC
是Spring中的一个模块
springmvc的作用struts2一致 都属于表现层框架
springmvc处理流程:
1.用户请求发送到前端控制器DispatcherServlet
2.DispatcherServlet收到请求调用HandlerMapping处理映射器
3.HandlerMapping处理映射器会根据请求url找到具体的处理器,生成处理器对象以及处理器拦截器,并返回给DispatcherServlet
4.DispatcherServlet通过HandlerAdapther处理器适配器调用处理器
5.执行处理器(Controller)
6.Controller执行完成返回ModelAndView
7.HandlerAdapther将controller的处理结果返回给DispatcherServlet
8.DispatcherServlet将ModelAndView传给视图解析器ViewReslover
9.视图解析器对结果进行解析并返回具体的view
10.DispatcherServlet对view进行渲染(就是将模型数据填充到视图)
11.DispatcherServlet响应给用户
springmvc的运行原理:
前端控制器DispatcherServlet:
相当于MVC中的C,是整个流程控制的中心
由它调用其他组件处理用户的请求
它的存在主要是降低了不同组件之间的耦合性
处理器映射器HandlerMapping:
处理器映射器负责根据用户请求的url找到处理器(Handler)
处理器Handler:
后端处理器,对具体的用户请求进行处理的
处理器主要用来处理具体的业务请求,所以处理器一般是需要程序员自己开发的-----Controller
处理器适配器:
通过处理器适配器对处理器进行执行
视图解析器ViewResolver:
负责将处理结果生成view视图
视图View:
最常用的视图----jsp
springmvc的三大组件:
处理器映射器 处理器适配器 视图解析器
需要用户开发的组件:处理器Handler--controller 视图view---jsp
我们不需要做任何配置就可以使用这些组件,因为springmvc已经默认加载了这些组件
只需要在配置文件中控制器类的自动扫描:
<context:component-scan base-package="controller包">
注解映射器和适配器:
配置处理器映射器
springmvc.xml
<bean class=".........................RequestMappingHandlerMapping">
注解:
@RequestMapping(url)
定义请求url到处理器功能方法的映射
配置处理器适配器
对标记@RequestMapping的方法进行适配
springmvc.xml
<bean class="............">
直接配置处理器映射器和处理器适配器比较麻烦,可以使用注解驱动来加载:
<mvc:annotation-driven/>
使用注解驱动可以自动加载处理器映射器和处理器适配器
视图解析器:
springmvc.xml
<bean class=".......................InternalResourceViewResolver">
<!--配置逻辑视图的前缀-->
<property name="prefix" value="/jsp"/>
<!--配置逻辑视图的后缀-->
<property name="suffix" value=".jsp"/>
</bean>
a
/jsp/a.jsp
最终jsp的物理地址:前缀+逻辑视图名+后缀
Controller:
ModelAndView
参数绑定:
Controller的方法中可以使用的参数类型:
处理器(Controller)能够识别处理的参数类型:
默认支持的参数类型:
HttpServletRequest
获取请求信息
HttpServletResponse
处理响应信息
HttpSession
得到存到session域中的对象
Model:
还可以使用Model向页面传递参数
Model----接口
@RequestMapping("/selectAllStu")
public ModelAndView selectAllStu(){
}
@RequestMapping("/selectAllStu")
public String selectAllStu(Model m){
List list=.....
m.addAttribute("list",list);
return "select";
}
ModelMap:
ModelMap是Model的实现类
也可以通过ModelMap向页面传递数据
使用ModelMap和使用Model的效果是一样的
使用Model的时候springmvc会实例化ModelMap
@RequestMapping("/selectAllStu")
public String selectAllStu(ModelMap m){
List list=.....
m.addAttribute("list",list);
return "select";
}
接收请求参数:
绑定简单类型
当请求的参数名称和controller的方法的形参的名称一致,请求参数和形参会进行绑定
简化了获取请求参数的方法
<form action=".../login">
<input type="text" name="uname">
.....
<form>
@RequestMapping("/login")
public String login(String uname){
}
支持的数据类型:
整型 int Integer
字符串 String
单精度浮点型 float Float
双精度浮点型 double Double
布尔型boolean Boolean
数据类型可以使用基本数据类型也可以使用基本数据类型的包装类
推荐使用包装类型
因为基本数据类型不能为null
@RequestParam
可以使用@RequestParam处理简单类型的绑定
value:参数名字
required:是否必须 默认为true
defaultValue:默认值
绑定对象:
当表单提交的参数很多的时候,可以直接使用独享接收数据
要求:
对象的属性名和表单中input的name属性一致
对象的属性名和请求参数的参数名一致
class User{
private String uname;
private String pwd;
private int age;
}
<input type="text" name="uname">
<input type="text" name="pwd">
<input type="text" name="age">
Controller:
@RequestMapping("...")
public String add(User user){
}
class User{
private String uname;
private String pwd;
private int age;
private Card c;
}
class Card{
private int cid;
private String cname;
}
<input type="text" name="uname">
<input type="text" name="pwd">
<input type="text" name="age">
<input type="text" name="c.cid">
<input type="text" name="c.cname">
绑定数组:
例如多选框需要同时接收多个值存到数组中
表单中name的值都是controller中形参的数组名
在controller的方法中定义形参数组
请求参数的名字和形参的数组名一致
绑定list:
controller方法的形参使用List
表单中input的name值 list名[下标].元素属性
@RequestMapping:
通过@RequestMapping注解定义不同的处理器映射规则
用在方法上:
@RequestMapping("/selectAll")
@RequestMapping(value={"select","selectAll"})
value的值可以是数组,可以将多个url映射到同一个方法
添加到类上:
在class上添加@RequestMapping(url)指定访问当前controller中方法的通用前缀
也就是访问该类下的方法都必须以执行的url开头
限定请求方法:
@RequestMapping(method=RequestMethod.GET) 限制只能使用get访问
@RequestMapping(method=RequestMethod.Post) 限制只能使用Post访问
@RequestMapping(method={RequestMethod.GET,RequestMethod.Post}) get和post都可以访问
Controller方法的返回值:
1.ModelAndView
可以在Controller方法中定义ModelAndView对象并返回
对象中可以添加数据,指定视图
2.返回void
在controller方法的形参上定义request和response
使用request或response指定响应结果
3.返回字符串-------官方推荐的方式*********
a.逻辑视图名
controller方法可以以字符串的形式返回逻辑视图名,视图解析器会解析为物理的视图地址
b.redirect重定向
controller方法返回的字符串可以重定向到一个url地址
return "redirect:/。。。";
c.forward转发
return "forward:/..."
异常处理器
springmvc在请求处理中出现的异常信息交由异常处理器进行处理的
可以自定义异常处理器实现一个系统的异常处理逻辑
自定义异常处理器:
1.实现HandlerExceptionResolver接口
2.实现方法,在方法中写异常处理
3.在springmvc.xml中添加
配置全局异常处理器
文件上传
jsp页面的要求:
1.必须在表单中
2.表单提交的方式–post
3.form标签中指定enctype=“multipart/form-data”
4.
1.导入fileupload的jar包以及依赖包io
2.在springmvc的配置文件中配置文件上传解析器
<bean is="" class="....">
3.Controller
controller中有形参 MultipartFile 形参的名字和表单中的name属性值一致
json数据交互:
@RequestBody
用于读取http请求内容(字符串),通过springmvc将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上
@RequestMapping("…")
public String test(@RequestBody User user){
}
@ResponseBody
用于将Controller方法返回的对象,通过springmvc转换为指定格式的数据:json xml,再通过response响应给客户端
@RequestMapping("..")
public @ResponseBody User test(){
}
Restful支持
是一个资源定位及资源操作的风格
不是一个标准也不是一个协议,至少一种风格
基于这种风格的软件可以更简洁,更有层次,也更易于实现缓存机制
传统方式:
http://127.0.0.1:8080/web/test.action?id=1
http://127.0.0.1:8080/web/1
1. @RequestMapping("/web/{id}")
2. (@PathVariable Integer id) 形参的值是获取的url的参数
3.
拦截器
类似于Servlet中的过滤器
用于对处理器进行预处理和后处理
也就是在执行controller方法之前执行预处理或者是执行controller方法之后执行后处理
使用:
1.定义拦截器实现HandlerInterceptor接口
2.实现接口中的方法
afterCompletion(..)
Controller执行后且视图返回后执行该方法
可以用来记录日志
boolean preHandle(...)
Controller执行调用此方法
返回true表示继续执行 返回false终止执行
可以用于登录校验 权限拦截
postHandle
Controller执行后视图返回前调用改方法
可以相应给用户前对数据进行加工处理,比如可以在视图中加入一些公共的信息显示到到页面
3.在springmvc.xml中配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="....">
<bean class="自定义的拦截器的类">
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="....">
<bean class="自定义的拦截器的类">
</mvc:interceptor>
</mvc:interceptors>
MyBatis
持久层框架
JDBC:
1.注册驱动
2.获取连接对象
3.获取发送sql的对象---Statement PreparedStatement
4.设置sql以及sql中的参数
5.执行sql并获取sql的结果
6.对sql的执行结果进行解析
7.释放资源
jdbc的问题:
1.数据库连接对象频繁创建,频繁释放,影响系统性能
解决方法:使用数据库连接池
2.sql语句在代码中硬编码,造成代码不易维护
在实际使用中sql的变化可能比较大,sql的变动需要修改java代码
3.使用PreparedStatement向占位符传参数存在硬编码
4.对结果集解析存在硬编码
MyBatis:
持久层框架
主要就是方便我们持久层代码的开发
mybatis对jdbc操作数据库的过程进行了封装,是的开发者只需要关注sql自身,而不需要花精力去处理像注册驱动,获取数据库连接。。。。。
mybatis通过xml或者注解的方式将要执行的各种statement配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最终由mybatis框架执行sql并将结果映射为java对象并返回
常用的持久层框架:mybatis Hibernate
mybatis架构:
1.mybatis配置
SqlMapConfig.xml:
mybatis的全局配置文件,配置mybatis的运行环境等信息
mapper.xml:
sql映射文件,文件中配置了操作数据库的sql语句。
这个文件需要在SqlMapConfig.xml中加载
2.通过mybatis的环境等配置信息构造sqlSessionFactory会话工厂
3.由会话工厂创建sqlSession会话,操作数据库是通过sqlSession会话进行
4.Executor执行器
mybatis底层自定义Executor执行器接口操作数据库
这个接口有两个实现:
一个是基本执行器
一个是缓存执行器
5.Mapped Statement
Mapped Statement也是Mybatis的一个底层封装对象,它包装了mybatis的配置信息以及sql映射智能型。
mapper.xml文件中的一个sql对应着一个Mapped Statement对象,sql的id就是Mapped Statement的id
Mapped Statement对象的作用:
a、对sql执行的输入参数进行定义,包括HashMap 基本类型 POJO
Executor执行器通过Mapped Statement在执行sql前将输入的java对象映射到sql中
输入参数的映射就对应jdbc中对preparedStatement设置参数
b、对sql执行的输出结果进行定义,包括HashMap 基本类型 POJO
Executor执行器通过Mapped Statement在执行sql后将输出的结果映射到java对象中,
输出结果的映射过程就相当于jdbc中解析处理运行结果的过程
映射文件:
User.xml
<mapper namespace="命名空间">
<select id="" parameterType="参数类型" resultType="结果的类型">
</select>
</mapper>
sql中的参数:
#{}:表示一个占位符号
通过#{}就相当于preparedStatement向占位符中设置值
自动进行java类型和jdbc类型的转换
#{}可以防止sql注入
#{}可以接受简单类型或者是pojo的属性值
如果输入参数的类型(parameterType)是简单类型,#{}可以是value或者是其他名称
${}:表示拼接sql字符串
通过${}可以将输入参数parameterType传入的内容拼接在sql中且不进行jdbc类型转换
${}可以接受简单类型或者是pojo的属性值
如果输入参数的类型(parameterType)是简单类型,${}中只能是value
parameterType:指定输入参数类型
resultType:指定输出结果类型
mybatis可以将sql插叙结果的一行记录映射为resultType指定类型的对象
查询:
<select id="" parameterType="" resultType="">
</select>
selectOne()
selectList()
插入:
<insert id="" parameterType="">
<selectKey keyProperty="" order="After" resultType="返回的主键的类型">
</selectKey>
</insert>
mysql使用主键自增,selectKey将新插入的这条数据的主键返回
mysql主键自增:
<selectKey keyProperty="id" order="After" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
mysql使用uuid生成字符串的而逐渐:
<selectKey keyProperty="id" order="Before" resultType="java.lang.String">
select uuid()
</selectKey>
oracle使用序列生成主键:
<insert id="" parameterType="">
<selectKey keyProperty="" order="Before" resultType="返回的主键的类型">
</selectKey>
</insert>
<insert id="insertUser" parameterType="com.ytc.vo.User">
<selectKey keyProperty="id" order="Before" resultType="java.lang.Integer">
select 序列名.nextval from dual
</selectKey>
insert into.....
</insert>
删除:
<delete id="" parameterType="">
delete....
</delete>
修改:
<update id="" parameterType="">
update...
</update>
使用mybatis开发持久层,通常有两种方式:
1.原始dao开发方法
需要程序员编写dao接口和dao实现类
a.编写配置文件
b.编写dao接口
c.编写dao的实现类
在实现类中获取sqlSessionFactory---sqlSession---调用相关方法
原始dao开发的问题:
dao实现类中的方法存在重复代码
调用sqlSession的数据库操作方法的时候需要用到Mapped Statement的id,这个地方存在硬编码
sqlSession.select(命名空间.id)
2.Mapper接口开发方法----Mapper动态代理方式
mapper接口开发方法只需要程序员编写mapper接口(dao层接口),由mybatis框架根据接口定义创建接口的动态代理对象。
也就是我们只需要写dao接口,而不需要写dao的实现类
Mapper接口开发需要遵循的规范:
1.Mapper.xml文件中的namespace与mapper接口的类路径相同
2.mapped接口的方法名和mapper.xml文件中定义的每个statement的id相同
3.mapper接口中方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型一致
4.mapper接口中方法的返回值类型和mapper.xml中定义的sql的resultType类型一致
SqlMapConfig.xml:
mybatis的全局配置文件
属性信息
全局的配置参数
类型别名
类型处理器
事务管理
数据源
映射器
。。。。
properties:
SqlMapConfig.xml可以引用java属性文件中的信息
db.properties
driverclass=
<peoperties resource="db.properties"/>
${driverclass}
类型别名:
自定义类型别名:
<typeAliases>
<!--单个的定义别名-->
<typeAlias alias="user" type="com.ytc.vo.User"/>
<!--批量定义别名,扫描整个包下的类,别名就是类名(首字母大写小写都可以)-->
<package name="com.ytc.vo"/>
</typeAliases>
映射器:
mapper的配置有多种方法
1.使用相对于类路径的资源
<mapper resource=""/>
2.使用完全限定路径
<mapper url="">
3.使用mapper接口类路径
<mapper class="mapper映射文件对应的接口的类路径"/>
注意:此种方法要求mapper接口名称和mapper映射文件的名称相同而且在同一目录中
4.注册指定包下的所有mapper接口
<package name="...."/>
注意:此种方法要求mapper接口名称和mapper映射文件的名称相同并且放在同一目录下
映射文件mapper.xml:
mapper.xml映射文件中定义了操作数据库的sql
每个sql是一个statement,映射文件是mybatis的核心
<mapper namespace="">
</mapper>
namespace:
命名空间
当使用传统dao方式的时候,是指定指定的sql的时候,使用命名空间.sql的id
mapper接口方式的时候,命名空间应该和mapper接口类的权限命名一致
parameterType:
输入类型
可以是简单类型 对象 HashMap
sql中的输入参数:
#{}
${}
简单类型:
#{value} #{id}
${value}
pojo对象:
#{对象的属性名}
${对象的属性名}
<select id="..." parameterType="com.ytc.vo.User" resultType="...">
select * from user where id=#{id}
</select>
包装对象:
class QueryVo{
private User user;
}
输入参数的类型为QueryVo
#{user.username}
hashMap:
#{key}
resultType:
输出结果类型
输出简单类型
输出pojo对象:
输出单个的对象和输出多个对象的集合使用的resultType的一样的
当查询结果列的列名可以和对象的属性名一样对应的时候,可以直接映射到对象
如果列名和属性名不一致,可以通过定义resultMap
resultMap:
resultMap主要用来指定查询结果列和对象属性之间的映射关系
目的还是为了将查询结果封装为java对象
mapper.xml中定义resultMap
id:表示查询结果集的唯一标识
property:表示类中的属性
column:表示sql查询出的字段名
<resultMap id="xxxx" type="要映射到的实体类的类名">
<id property="属性名" column="主键列的列名"/>
<result property="属性名" column="结果列的列名">
</resultMap>
输出hashMap:
将输出的字段名称作为map的key
字段值作为map的value
动态sql
通过mybatis提供的各种标签方法实现动态的拼接sql
if
</if>
查询用户信息
查询所有用户
根据用户的id查询用户
根据用户名模糊查询用户
<select id="findUser" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="uname!=null and uname!=''">
and uname like '%${uname}%'
</if>
</select>
where
上面的需求也可以写成:
<select id="findUser" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="uname!=null and uname!=''">
and uname like '%${uname}%'
</if>
</where>
</select>
where标签可以自动的处理第一个and
foreach
当向sql中传递数组或者是List,mybatis可以使用foreach解析
1、List
select * from user where 1=1 and id in(....)
类中
List ids;
<if test="ids!=null and ids.size>0">
<foreach collection="ids" open=" and id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
2、数组
<if test="array!=null">
<foreach collection="array" index="index" open=" and id in(" close=")" item="item" separator=",">
#{item.属性名}
</foreach>
</if>
如果是单个的list,参数名称就是list
单个数组,参数名称就是array
如果是通过一个对象将list或者数组传递到sql,参数名称应该是对象中的属性名。
sql片段
sql中可以将重复的sql提取出来,使用的时候用include引用即可,最终达到sql重用的目的
<select id="findUser" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="uname!=null and uname!=''">
and uname like '%${uname}%'
</if>
</where>
</select>
上面的代码中可以将if判断抽取出来作为sql片段
<sql id="query_user_where">
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="uname!=null and uname!=''">
and uname like '%${uname}%'
</if>
</sql>
可以在需要用到的地方使用include包含:
<select id="findUser" parameterType="user" resultType="user">
select * from user
<where>
<include refid="query_user_where"/>
</where>
</select>
注意:如果引用其他映射文件(mapper.xml)中的sql片段,需要在引用时加上namespace
<include refid="namespace.sql片段的id"/>
关联查询:
一对一
方式一:
使用resultType
定义po类,这个类中包括了用户信息和身份证信息
定义专门的po类作为输出类型,其中定义了sql查询结果集的所有字段。
这个方法使用较为简单,企业中使用普遍。
方法二:
使用resultMap
定义专门的resultMap用于映射一对一的查询结果
<resultMap type="" id="">
<id property="" column=""/>
<result property="" column="">
<association property="" javaType="">
<id property="" column=""/>
<result property="" column="">
</association>
</resultMap>
一对多
sql
po类:
订单Order
List<Orderdetail> orderdetails;
订单明细 Orderdetail
mapper.xml
<select id="" resultMap="">
....
</select>
resultMap:
<resultMap type="......Order" id="">
<id....>
<result...>
<collection property="orderdetails" ofType="">
<id>
<result>
</collection>
</resultMap>
多对多
resultMap
延迟加载----懒加载
需要查询关联信息时,使用mybatis的延迟加载特性可以减少数据库的压力。
首次查询只查询主要信息,关联信息等用户获取时再加载。
在mybatis的配置文件中打开延迟加载的开关:
<settings>
<settig name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
查询缓存:
缓存的意义:
将用户经常查询的数据放在缓存(内存)中,用户查询数据就不用再去查询数据库,而是直接从缓存中获取数据,从而提高查询的效率。解决了高并发系统的性能问题。
一级缓存
一级缓存的作用域是同一个sqlsession
在同一个sqlSession中指向两次相同的sql时,第一查询数据库结束将查询的结果写到缓存,第二次查询的时候不再读取数据库,而是从缓存中直接获取,从而提高查询效率。
当一个sqlSession结束后,该sqlSession的缓存也就不存在了。
mybatis是默认开启一级缓存的。
如果sqlSession中执行了insert update delete操作并提交了事务,会清空sqlSession的一级缓存
二级缓存
二级缓存是多个sqlSession共享的,作用域是同一个namespace
不同的sqlSession两次执行相同的namespace下的sql语句并且向sql中传递相同的参数(最终执行的sql是相同的)。第一次执行后将查询结果保存到缓存,第二次会从缓存中直接获取数据不再查询数据库,从而提高查询的效率。
mybatis的二级缓存默认是不开启的,需要在配置文件中通过设置setting全局参数配置开启二级缓存。
开启二级缓存:
在mybatis的核心配置文件中SqlMapConfig.xml中
<setting name="cacheEnabled" value="true"/>
在mapper中使用
<cache/> 开启当前mapper的二级缓存
可以对单个的sql禁用二级缓存
<select id="" useCache="false">
</select>
刷新缓存:
如果sqlsession执行了commit操作,会对二级缓存进行刷新
执行insert update delete需要刷新缓存,不刷新会出现脏读
<insert flushCache="true">
mybatis中整合ehcache:
1.到入相关依赖包
2.缓存配置文件 ehcache.xml
3.开启ehcache缓存
二级缓存的使用场景:
主要用在访问比较多的并且对于查询的结果实时性要求不高的查询请求
电话账单
mybatis逆向工程:
自动生成po类和mapper映射文件
基于配置文件的mybatis—xml配置文件
mybatis基于注解的开发:
SqlMapConfig.xml这个文件还是该怎么写怎么写
注解开发只是用来代替mapper.xml映射文件
常用注解:
在dao接口方法上添加注解
@select
@insert
@update
@delete
@Result 实现结果集的封装
@Results 可以和@Result一起使用,封装多个结果集
@ResultMap 实现引用@Results定义封装
@One 实现一对一结果集的封装
@Many 实现一对多结果集的封装
@SelectProvider 实现动态sal映射
@CacheNamespace 实现注解二级缓存的使用
SSM整合(SpringMVC+Spring+MyBatis)
(一)整合的要点:
1.Spring框架整合MyBatis:
1.1 由Spring框架负责连接数据库;特征:不需要编程,只要求配置.
(1)Spring框架通常使用dbcp连接池连接数据库.
(2)Spring框架由SqlSessionFactoryBean负责创建符合MyBatis要求的SqlSessionFactory对象.
1.2 由Spring框架负责创建并提供Mapper对象.
(1)Spring框架提供一个MapperScannerConfigurer对象来创建Mapper对象;
(2)Spring框架由IoC容器缓存Mapper对象,并在需要的时候实施依赖注入.
总结要点:dbcp连接池+SqlSessionFactoryBean+MapperScannerCongfigurer
2.Spring框架针整合SpringMVC:
2.1 Spring框架针对业务组件和dao组件创建一个单独的IoC容器
(1)这个IoC容器是Web类型的IoC容器,被称为根容器(Root WebApplicationContext);
(2)这个IoC容器由监听器(ContextLoaderListener)在web服务器启动时创建;
2.2 SpringMVC框架负责表现层的IoC容器的创建
(1)表现层的IoC容器也是Web类型的IoC容器,由DispatcherServlet负责创建,
因此也被称为Servlet创建的IoC容器,表示为Servlet WebApplicationContext.
(2)表现层的IoC容器与业务层和持久化层的IoC容器是无缝整合:
I. 都是Spring框架的IoC容器,但是表现层的IoC容器是子容器,而业务层和持久化层的IoC容器是根容器.
II. 子容器与根容器的访问关系遵循双亲型委派模式.
总结要点:2个IoC容器的关系
(二)整合的流程(案例:不含验证码的简版登录模块):
1.创建Web工程,加载整合类库,设置xml编写的弹出机制;
说明:在myeclipse中补充配置tx和aop名称空间.
2.利用MyBatis的逆向工程,生成JavaBean、Dao接口及其mapper.xml文件.
-----------------------连接数据库-----------------------------------------------------
3.创建MyBatis框架的配置文件:mybatis-config.xml
(1)配置MyBatis的日志输出形式;
(2)配置JavaBean的别名,方便在mapper文件中使用;
(3)配置Mapper文件的引用.
4.创建Spring与MyBatis框架的整合配置文件:spring-mybatis.xml
4.1 注册dbcp连接池-BasicDataSource对象
特点:使用占位符
(1)在项目中创建连接数据库的properties文件
(a)配置连接数据库的4大参数
(b)配置连接池的伸缩性.
(2)使用context:property-placeholder标签指明properties文件的位置
4.2 配置SqlSessionFactoryBean,目的是创建SqlSession对象
特征:需要依赖注入连接池.
-------------------------创建Dao对象并测试----------------------------------------------------
5.在spring-mybatis.xml文件中配置MapperScannerConfigure,目的是创建Mapper对象.
配置时,需要明确如下2个属性:
(1) dao包的位置
(2) SqlSessionFactory对象在IoC容器中的名称(beanName).
6.使用JUnit4,针对UserDao接口中所定义的方法,测试Mapper对象.
-------------------------创建Service组件并实施AOP配置及其测试----------------------
7.定义UserService接口
8.定义UserService接口的实现类
9.在spring-mybatis.xml文件中,采用注解方式,创建业务组件对象并实施依赖注入
10.使用JUnit4,第一次测试UserService的接口方法
11.采用注解的方式,重构定义了环绕通知的POJO类
目的:针对Service对象的业务方法实施跟踪记录
12.在spring-mybatis.xml文件中,实施基于注解的普通切面的配置
13.使用JUnit4,第二次测试UserService的接口方法
14.在spring-mybatis.xml配置文件中,配置基于注解驱动的事务管理
15.使用JUnit4,第三次测试UserService接口方法,主要测试事务管理是否有效.
--------------------------------创建控制器组件--------------------------------------------------------
16.SpringMVC的表现层的开发:
16.1 准备spring mvc的web结构:
(1)在webroot下创建静态资源目录:css,js,images
(2)在WEB-INF目录下,创建目录:config,jsp,resources
16.2 在web.xml文件中:
(1)注册总控制器-DispatcherServlet(请求分发器)
(2)注册编码过滤器
*(3)注册监听器,创建web类型的IoC容器(管理Service,Dao,连接池,事务管理器…);
16.3 编写控制器UserController:
(1)针对JavaBean实施注解校验,非空,email格式等校验
(2)针对成功的登录用户,记录最新的登录时间和ip地址,并同步到数据库中,并且将用户存入到HttpSession对象中;
(3)转发到jsp输出页面,输出登录用户的信息.对于非法用户,返回登录页面,产生错误信息.
16.4 编写LoginForm.jsp页面(输入页面)
16.5 编写UserInfo.jsp页面(输出页面)
16.6 开发登出功能,实施重定向返回到登录页面.