Spring
1. spring的注入方式
a . bean配置
-
设值注入
- setXxx()方法,
-
构造注入
- 标签
-
p命名空间
- xmlns:p=“http://www.springframework.org/schema/p” 并在标签中 P:name=""
-
自动装配 (只适用于引用类型)autowire=“byName | byType | constructor | no” (不建议多次使用)
- 在< bean id="" autowire=“byName” /> ,当id的类中有和IOC容器中bean的id相同时,自动装配
- byName : bean的id值=类的属性名
- byType : 其他bean的类型(class)是否与该类的ref属性类型一致(当前IOC容器中只能有一个bean满足条件)
- constructor : 其他bean的类型(class)是否与该类的构造方法参数的类型一致,本质是byType
- 在头文件的beans标签中添加统一自动装配:default-autowire=“byName”
- 自动装配虽然可以减少代码量,但是会降低程度的可读性,使用时需要谨慎
- 在< bean id="" autowire=“byName” /> ,当id的类中有和IOC容器中bean的id相同时,自动装配
b . 注解方式
-
@Component细化:
- @Repository Dao层
- @Service service层
- @Controller controller层
-
配置包扫描器:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<context:component-scan base-package="com.test.pojo" />
- 在声明前加上 @Value("")
2. 使用注解实现声明式事务
1.需要的包:
- spring-tx.jar
- ojdbc.jar 驱动
- commons-dbcp.jar 连接池使用到的数据源
- commons-pool.jar 连接池
- spring-jdbc.jar
- aopalliance.jar aop相关
2.增加事务tx的命名空间
3.增加对事务的支持(核心):
<tx:annotation-driven transaction-manager=“txManager” />
配置事务管理器:
配置数据库相关:
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="" />
<property name="username" value="system" />
<property name="password" value="123456" />
<property name="maxIdle" value="10" />
<property name="maxWaitMillis" value="1000" />
</bean>
4.将需要成为事务的方法 前增加注解:
@Transactional(readOnly=false,propagation=Propagation.REQUIRED,rollBackFor=...)
3. AOP
需要的jar:
- aopliance.jar
- aspectjweaver.jar
通知类型:org.springframework.aop.
- 前置通知:MethodBeforeAdvice 接口方法 before()
- 后置通知:AfterReturningAdvice 接口方法 afterReturning()
- 异常通知:ThrowsAdvice 接口方法 无
- 环绕通知:MethodInterceptor 接口方法 invoke()
<!-- 配置前置通知 切面 -->
<bean id="logBefore" class="com.test.aop.LogBefore"></bean>
<!-- 关联切入点和切面 -->
<aop:config >
<!-- 配置切入点 -->
<aop:pointcut id="pointcut" expression="execution(public void com.test.service.demoService.DemoServiceImpl.addUser())" />
<!-- 连接线 -->
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut" />
</aop:config>
异常通知必须实现方法:
public void afterThrowing(Throwable ex)
or
public void afterThrowing(Method method, Object[] args, Object target, Throwable ex)
环绕通知:
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object result = null;
try {
System.out.println("环绕-前置通知");
//在此之前的为前置通知
result = mi.proceed(); //控制目标方法是否执行
//在此之后的为后置通知
System.out.println("环绕-后置通知:目标对象:" + mi.getThis() + ",调用的方法:" + mi.getMethod().getName() +
",参数个数:" + mi.getArguments().length + ",返回值:" + result);
}catch (Exception e){
//异常通知
System.out.println("环绕-异常通知");
}
return result;
}
注解实现AOP
- 前置: @Before
- 后置: @AfterReturning
- 异常: @AfterThrowing
- 环绕: @Around
- 最终: @After
注解形式AOP,需设置扫描器,扫描器会将指定的包中的 @Component @Service @Repository @Controller修饰的类产生的对象增加到IOC容器
通过注解形式实现的AOP,若要获取目标对象的一些参数,则需要使用一个对象:JoinPoint
@Component("logAnnotation")
@Aspect //表示此类是一个AOP通知
public class LogAnnotation {
// 前置通知
@Before("execution(public void addUser())") // 属性定义触发时机(切点)
public void myBefore(JoinPoint jp){
System.out.println("《注解》-前置通知:目标对象:" + jp.getTarget() + ",方法名:" + jp.getSignature().getName() +
",参数个数:" +jp.getArgs().length );
}
// 后置通知
@AfterReturning(pointcut = "execution(public void deleteUser())", returning = "returningValue") // 属性定义触发时机(切点)
public void myAfter(JoinPoint jp, Object returningValue){ //需要声明该方法有返回值, returningValue 是返回值
System.out.println("《注解》-后置通知:目标对象:" + jp.getTarget() + ",方法名:" + jp.getSignature().getName() +
",参数列表:" + Arrays.toString(jp.getArgs()) + ",返回值:" + returningValue );
}
// 异常通知:如果只捕获特定类型的异常,则可以通过第二个参数实现:e
@AfterThrowing(pointcut = "execution(public void addUser())", throwing = "e")
public void myException(JoinPoint jp, NullPointerException e){
System.out.println("《注解》-异常通知: " + e.getMessage());
}
// 环绕通知
@Around("execution(public void addUser())")
public void myAround(ProceedingJoinPoint pjp){
//前置通知
System.out.println("《注解-环绕》-前置通知");
try{
pjp.proceed(); // 执行方法,抛出的是Throwable
System.out.println("《注解-环绕》-后置通知");
}catch (Throwable e){
// 异常通知
System.out.println("《注解-环绕》-异常通知");
}finally {
// 最终通知
System.out.println("《注解-环绕》-最终通知");
}
}
//单独的最终通知
@After("execution(public void addUser())")
public void myAfter(){
System.out.println("《注解-环绕》-【单独的最终通知】");
}
}
开启注解对AOP的支持
< aop:aspectj-autoproxy></aop:aspectj-autoproxy>
通过Scheme配置AOP
xmlns:aop=“http://www.springframework.org/schema/aop”
类似于实现接口的方式
- 编写一个普通的类
// Schema实现的AOP不需要实现接口,只需要在xml里配置
public class LogSchema {
// 前置通知
public void before(JoinPoint jp){
System.out.println("【Schema】前置通知");
}
//后置通知
public void afterReturning(JoinPoint jp, Object returnValue){
System.out.println("【Schema】后置通知:目标对象:" + jp.getThis() + ",方法名:" + jp.getSignature().getName() + ",参数个数:"
+ jp.getArgs().length + ", 返回值:" + returnValue);
}
// 环绕通知
public Object around(ProceedingJoinPoint pjp){
System.out.println("【Schema】环绕-前置通知");
Object result = null;
try {
//在此之前的为前置通知
result = pjp.proceed(); //控制目标方法是否执行
//在此之后的为后置通知
System.out.println("【Schema】环绕-后置通知:目标对象:" + pjp.getThis() + ",调用的方法:" + pjp.getSignature().getName() +
",参数个数:" + pjp.getArgs().length + ",返回值:" + result);
}catch (Throwable e){
//异常通知
System.out.println("【Schema】环绕-异常通知");
}
return result;
}
}
- 将该类通过配置,转为一个通知
如果要获取目标对象的信息:
- 注解、schema:JoinPoint
- 接口:Method method, Object[] args, Object target
<!-- 通过Schema实现AOP -->
<bean id="logSchema" class="com.test.aop.LogSchema">
</bean>
<!-- 关联切入点和切面 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut id="pcSchema"
expression="execution(public void com.test.service.demoService.DemoServiceImpl.addUser())"/>
<!-- 连接线 Schema方式不需要这个
<aop:advisor advice-ref="logSchema" pointcut-ref="pcSchema" />
-->
<aop:aspect ref="logSchema">
<!-- pointcut-ref:连接线 returnValue: 返回值 -->
<aop:before method="before" pointcut-ref="pcSchema"/>
<aop:after-returning method="afterReturning" pointcut-ref="pcSchema" returning="returnValue"/>
<aop:around method="around" pointcut-ref="pcSchema"/>
</aop:aspect>
</aop:config>
Spring 开发Web项目
Java项目中从main开始启动,可以初始化IOC容器,在Web项目中从服务器启动时,需通过监听器初始化IOC容器
需要用到 spring-web.jar ,并在web.xml中进行配置
<!-- 配置spring-web.jar 提供的监听器,可以在服务器启动时初始化IOC容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<!--
1. 必须告诉监听器此容器的位置:context-param
2. 默认约定的位置:WEB-INF/applicationContext.xml
-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
配置时必须告诉监听器此容器的位置,或者用默认的名称放在默认约定的位置:
WEB-INF/applicationContext.xml
拆分Spring配置文件
Web项目拆分配置:
- 三层结构
- UI(html/css/jsp/servlet)
- Service
- Dao
- 公共 数据库
- 功能结构
- 学生管理系统的功能结构:学生相关配置、班级相关配置…
Web项目合并配置:
1.在web.xml的context-param的classpath:中配置
<param-value>
classpath:applicationContext.xml,
classpath:applicationContext-1.xml,
classpath:applicationContext-2.xml
</param-value>
或
(推荐)
<param-value>
classpath:applicationContext.xml,
classpath:applicationContext-*.xml
</param-value>
2.在主配置文件applicationContext.xml中引入其他文件
<import resource="applicationContext-*.xml" />
...
springIOC容器与Servlet容器搭建通道,传递数据 (servlet与service)
在Servlet的init初始化方法中,获取SpringIOC容器中的bean对象
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext("");
xxxService = (xxxxService) context.getBean("");
SpringMVC
SpringMVC流程:
-
用户发送请求至前端控制器DispatcherServlet。
-
DispatcherServlet收到请求调用HandlerMapping处理器映射器。
-
处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
-
DispatcherServlet调用HandlerAdapter处理器适配器。
-
HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
-
Controller执行完成返回ModelAndView。
-
HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
-
DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
-
ViewReslover解析后返回具体View。
-
DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
-
DispatcherServlet响应用户。
SpringMVC简介:
SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化日常Web开发。(处理业务数据的对象和显示业务数据的视图之间存在紧密耦合)。
MVC设计模式:
MVC即Model-View-Controller,将应用按照Model(模型)、View(视图)、Controller(控制)这样的方式分离。
-
视图(View):代表用户交互界面,对于Web应用来说,可以是HTML,也可能是jsp、XML和Applet等。一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上的业务流程的处理。业务流程的处理交予模型(Model)处理。
-
模型(Model):是业务的处理以及业务规则的制定。模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计是MVC最主要的核心。MVC设计模式告诉我们,把应用的模型按一定的规则抽取出来,抽取的层次很重要,抽象与具体不能隔得太远,也不能太近。MVC并没有提供模型的设计方法,而只是组织管理这些模型,以便于模型的重构和提高重用性。
-
控制(Controller):可以理解为从用户接收请求, 将模型与视图匹配在一起,共同完成用户的请求。划分控制层的作用也很明显,它清楚地告诉你,它就是一个分发器,选择什么样的模型,选择什么样的视图,可以完成什么样的用户请求。控制层并不做任何的数据处理。
适配器的作用
SpringMVC涉及的映射器负责将前端请求的url映射到配置的处理器,视图解析器将最终的结果进行解析,但中间为什么要经过一层适配器呢,为什么不经映射器找到controller后直接执行返回呢?
那是因为SpringMVC为业务处理器提供了多种接口实现(例如实现了Controller接口),而适配器就是用来根据处理器实现了什么接口,最终选择与已经注册好的不同类型的Handler Adapter进行匹配,并最终执行,例如,SimpleControllerHandlerAdapter是支持实现了controller接口的控制器,如果自己写的控制器实现了controller接口,那么SimpleControllerHandlerAdapter就会去执行自己写的控制器中的具体方法来完成请求。
SpringMVC的特点:
- 清晰的角色划分:控制器(controller)、验证器(validator)、 命令对象(command object)、表单对象(formobject)、模型对象(model object)、 Servlet分发器(DispatcherServlet)、处理器映射(handler mapping)、视图解析器(view resolver)等。每一个角色都可以由一个专门的对象来实现。
- 强大而直接的配置方式:将框架类和应用程序类都能作为JavaBean配置,支持跨多个context的引用,例如,在web控制器中对业务对象和验证器(validator)的引用。
- 可适配、非侵入:可以根据不同的应用场景,选择合适的控制器子类 (simple型、command型、form型、wizard型、multi-action型或者自定义),而不是从单一控制器 (比如Action/ActionForm)继承。
- 可重用的业务代码:可以使用现有的业务对象作为命令或表单对象,而不需要去扩展某个特定框架的基类。
- 可定制的绑定(binding) 和验证(validation):比如将类型不匹配作为应用级的验证错误, 这可以保存错误的值。再比如本地化的日期和数字绑定等等。在其他某些框架中,你只能使用字符串表单对象,需要手动解析它并转换到业务对象。
- 可定制的handlermapping和view resolution:Spring提供从最简单的URL映射, 到复杂的、专用的定制策略。与某些webMVC框架强制开发人员使用单一特定技术相比,Spring显得更加灵活。
- 灵活的model转换:在Springweb框架中,使用基于Map的 键/值对来达到轻易地与各种视图技术的集成。
- 可定制的本地化和主题(theme)解析:支持在JSP中可选择地使用Spring标签库、支持JSTL、支持Velocity(不需要额外的中间层)等等。
- 简单而强大的JSP标签库(SpringTag Library):支持包括诸如数据绑定和主题(theme) 之类的许多功能。
- JSP表单标签库:在Spring2.0中引入的表单标签库,使得在JSP中编写 - 表单更加容易。
Spring Bean的生命周期可以被限制在当前的HTTP Request或者HTTP Session。
SpringMVC的优点:
- 让我们能非常简单的设计出干净的Web层和薄薄的Web层
- 进行更简洁的Web层的开发
- 天生与Spring框架集成(如IoC容器、AOP等)
- 提供强大的约定大于配置的契约式编程支持
- 非常灵活的数据验证、格式化和数据绑定机制
- 支持Restful风格
SpringMVC入门程序:
web.xml
<web-app>
<servlet>
<!-- 加载前端控制器 -->
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
加载配置文件
默认加载规范:
* 文件命名:servlet-name-servlet.xml====springmvc-servlet.xml
* 路径规范:必须在WEB-INF目录下面
修改加载路径:
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
springmvc.xml
<beans>
<!-- 配置映射处理器:根据bean(自定义Controller)的name属性的url去寻找handler;springmvc默认的映射处理器是BeanNameUrlHandlerMapping-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置处理器适配器来执行Controller ,springmvc默认的是SimpleControllerHandlerAdapter
-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置自定义Controller -->
<bean id="myController" name="/hello.do" class="org.controller.MyController"></bean>
<!-- 配置sprigmvc视图解析器:解析逻辑视图;
后台返回逻辑视图:index
视图解析器解析出真正物理视图:前缀+逻辑视图+后缀====/WEB-INF/jsps/index.jsp
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsps/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
自定义处理器
public class MyController implements Controller{
public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
ModelAndView mv = new ModelAndView();
//设置页面回显数据
mv.addObject("hello", "欢迎学习springmvc!");
//返回物理视图
//mv.setViewName("/WEB-INF/jsps/index.jsp");
//返回逻辑视图
mv.setViewName("index");
return mv;
}
}
SpringMVC常用注解及其作用
@Controller:标识这个类是一个控制器
@RequestMapping:给控制器方法绑定一个uri
@ResponseBody:将java对象转成json,并且发送给客户端
@RequestBody:将客户端请求过来的json转成java对象
@RequestParam:当表单参数和方法形参名字不一致时,做一个名字映射
@PathVarible:用于获取uri中的参数,比如user/1中1的值
Rest风格的新api:
@RestController相当于@Controller+ @ResponseBody
@GetMapping@DeleteMapping@PostMapping@PutMapping
其他注解:
@SessionAttribute:声明将什么模型数据存入session
@CookieValue:获取cookie值
@ModelAttribute:将方法返回值存入model中
@HeaderValue:获取请求头中的值
SpringMVC和Struts2的对比
框架机制:SpringMVC的入口是servlet,而Struts2是filter。
Filter在容器启动后就初始化,服务停止后销毁,晚于Servlet;Servlet在是在调用时初始化,先于Filter调用,服务停止后销毁。
拦截机制:
Struts2:
1、Struts2框架是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype(否则会出现线程并发问题),然后通过setter,getter吧request数据注入到属性;2、一个Action对应一个request,response上下文,在接收参数时,可以通过属性接收,说明属性参数是让多个方法共享的;
3、Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
SpringMVC:
1、SpringMVC是方法级别的拦截,一个方法对应一个Request上下文,所以方法直接基本上是独立的,独享request,response数据。而每个方法同时又何一个url对应,参数的传递是直接注入到方法中的,是方法所独有的。处理结果通过ModeMap返回给框架;2、在Spring整合时,SpringMVC的Controller Bean默认单例模式Singleton,所以默认对所有的请求,只会创建一个Controller,有应为没有共享的属性,所以是线程安全的,如果要改变默认的作用域,需要添加@Scope注解修改;
Struts2有自己的拦截Interceptor机制,SpringMVC这是用的是独立的Aop方式,这样导致Struts2的配置文件量还是比SpringMVC大。
性能方面:SpringMVC实现了零配置,由于SpringMVC基于方法的拦截,有加载一次单例模式bean注入。而Struts2是类级别的拦截,每次请求对应实例一个新的Action,需要加载所有的属性值注入,所以,SpringMVC开发效率和性能高于Struts2。
配置方面:spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少);
SpringMVC可以认为已经100%零配置。
设计思想:Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
集成方面:SpringMVC集成了Ajax。
注意:springmvc是单例模式的框架,但它是线程安全的,因为springmvc没有成员变量,所有参数的封装都是基于方法的,属于当前线程的私有变量. 因此是线程安全的框架。所以效率高。
struts action是多例的。所以可以使用成员变量获取参数。所以效率低。
Mybatis
MyBatis 可以简化JDBC操作,实现数据持久化
- ORM: Object Relational Mapping
- ORM概念:MyBatis是ORM的一个实现 / Hibernate
- ORM可以使得开发人员,像操作对象一样操作数据库表
开发Mybatis步骤:
配置Mybatis
- jar包: mybatis.jar ojdbc6.jar
- config.xml : 配置数据库信息 和 需要加载的映射文件
- 表 - 类
- 映射文件xxxMapper.xml : 增删改查标签 < select>
- 测试类:sqlSession.selectOne(“需要查询的SQL的namespace.id”,“SQL的参数值”);
config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
default和id值保持一致,通过default找到id
-->
<configuration>
<environments default="development"> <!-- 默认环境,即环境的id -->
<environment id="development">
<!-- 配置事务的提交方式:
1.用JDBC方式进行事务处理(commit rollback close)
2.MANAGER:将事务交由其他组件去托管(spring, jobss),默认会关闭连接
<property name="closeConnection" value="false" /> // 设置为不关闭
-->
<transactionManager type="JDBC"/>
<!-- 连接方式 UNPOOLED: 传统的连接方式(每次访问数据库都需要打开和关闭等操作)
POOLED: 使用数据库连接池
JNDI: 从tomcat获取一个内置的数据库连接池
-->
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"/>
<property name="username" value="system"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<mappers>
<!-- 在配置文件中加载映射文件 -->
<mapper resource="personMapper.xml"/>
</mappers>
</configuration>
xxxMapper.xml
<?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">
<!--
namespace 映射文件路径
id 区分查询语句
resultType 返回值
parameterType 传入参数的类型,这里是id的类型int
-->
<mapper namespace="com.pojo.personMapper">
<select id="queryPersonById" resultType="com.pojo.Person" parameterType="int">
select * from person where id = #{id}
</select>
</mapper>
Mybatis的CRUD:
// 加载Mybatis文件,访问数据库
Reader reader = Resources.getResourceAsReader("config.xml");
// 当config.xml里的default不是所需的时,可以在build里强行切换数据库环境
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader, "development");
// SqlSessionFactory -- Connection
SqlSession sqlSession = sessionFactory.openSession();
// 通过配置文件personMapper.xml里的namespace和id获得sql语句
String statement = "com.pojo.personMapper.addPerson";
Person person = new Person(8, "cui8", 27);
// insert 插入一个person
int count = sqlSession.insert(statement, person);
//需要 commit
sqlSession.commit();
System.out.println("增加" + count + "个成功");
sqlSession.close();
Mybatis 约定:
输入参数parameterType 和 输出参数resultType,在形式上都只能有一个
如果输入参数是简单类型(8个基本+String),是可以使用任何占位符#{xxx}的;
如果是对象类型,则必须是对象的属性:#{属性名}
如果使用的事务方式为 jdbc,则需要手动提交:sqlSession.commit()
Mybatis动态代理方式的CRUD
原则:约定优于配置
硬编码方式:abc.java
Configguration conf = new Configuration();
con.setName(“myProject”);
配置方式:abc.xml
< name>myProject< /name>
约定:默认值就是myProject
具体实现步骤:
- jar包,config.xml ,mapper.xml…
(不同处)约定的目标:
省略掉Statement,即根据约定直接定位出SQL语句
建立一个接口PersonMapper
约定:
1. 方法名和mapper.xml 文件中标签的id值一样
2. 方法的输入参数类型和parameterType一样
3. 方法的返回值和resultType一样
如: Person queryPersonById(int id);
要实现接口中的方法 和 Mapper.xml中的SQL标签一 一对应,还需要:
namespace的值,就是接口的全类名(接口–mapper.xml一 一对应)
匹配的过程:(约定过程)
- 根据接口名 找到mapper.xml文件 (根据的是namespace=接口全类名)
- 根据接口的方法名 找到mapper.xml文件中的SQL标签(方法名=SQL标签id值)
根据以上两点可以保证:当调用接口中的方法时,程序能自动定位到某一个Mapper.xml文件中的SQL标签
习惯:SQL映射文件 和 接口放在同一位置(注意修改config.xml中加载mapper.xml文件的路径)
以上,可以通过接口的方法————> 映射到SQL语句
// 通过约定接口的方式
PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
personMapper.updatePerson(person); // 根据接口的方法 ---> 自动查找到SQL语句
优化:
- 可以将数据库信息放入db.properties,再通过 ${key} 动态引入
<configuration>
<properties resource="db.properties" />
- Mybatis 全局参数
//开启缓存
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="" value="" />
...
</settings>
-
设置类的别名(忽略大小写)
-
a. 设置单个别名
在config.xml中,
-
< typeAliases> < typeAlias type="org...Person" alias="Person" />...
- b. 批量设置别名,别名就是不带包名的类名
// 包名
< typeAliases> < package name="org.test" />...
// Mybatis 还内置了一些常见类的别名:_integer/_byte/_long/int/boolean...
-
类型处理器 (类型转换器)(将Java类型转换为JDBC类型,如int转换为oracle的number类型)
-
a. Mybatis 自带一些常见的类型处理器
如:BooleanTypeHandler:Boolean/boolean --> 任何兼容的布尔值
IntegerTypeHandler:Integer/int --> 任何兼容的数字和整形
… -
b. 自定义Mybatis 类型处理器
Java类型 --> 数据库(JDBC类型)
示例:
实体类Student: boolean stuSex true:男 false: 女
表student:number stuSex 1:男 0:女
-
自定义类型转换器(boolean – number) 步骤:
a. 创建类型转换器,要实现 TypeHandler接口 或继承BaseTypeHandler(更简单)
b. 在config.xml 中配置转换器
<!-- 类型处理器,将java的boolean类型 转换为 jdbc的number类型 -->
<typeHandlers>
<typeHandler handler="com.mybatis.MyTypeHandler" javaType="Boolean" jdbcType="INTEGER" />
</typeHandlers>
c. 更改映射文件
<!-- 验证类型转换器
1.如果类的属性 和 表的字段类型 能够合理识别(String - varchar2),则可以使用resultType,否则使用resultMap(boolean-number)
2.如果类的属性名 和 表的字段名 能够合理识别(String - varchar2),则可以使用resultType,否则使用resultMap(boolean-number)
-->
<select id="queryPersonByIdWithConverter" resultMap="resultPerson" parameterType="int">
select * from person where id = #{id}
</select>
<!-- 建立Person属性和表的字段的对应关系 主键id,非主键result , 再设置需要转换的类型-->
<resultMap id="resultPerson" type="person">
<id property="id" column="id" />
<result property="sex" column="sex" javaType="boolean" jdbcType="INTEGER" />
</resultMap>
类型转换的增加
// 更改SQL语句中需要转换的字段
#{sex,javaType=boolean,jdbcType=INTEGER}
注意:
1. 映射文件路径
<!-- 在配置文件中加载映射文件 IDEA里无法加载src下的xml文件 因此改用url class package等方式(接口与映射文件名称相同),
或将xml文件放到resources目录-->
<!-- 通过包名设置路径 -->
<package name="com.mybatis.myInter" />
2. 映射文件和config.xml的jdbcType的类型
integer 必须写成大写形式:INTEGER
5. 取值符号
- 简单类型
#{任意值} // 自动给String类型加上单引号’’ (自动类型转换)
${value} // 原样输出,但适合于动态排序(动态字段),其中的标识符只能是value - 对象类型
#{属性名}
${属性名}