参考资料:
https://www.cnblogs.com/jingmoxukong/p/9408037.html#1.-%E4%B8%80%E8%88%AC%E9%97%AE%E9%A2%98
https://www.edureka.co/blog/interview-questions/spring-interview-questions/
https://blog.csdn.net/a745233700/article/details/80963758
https://blog.csdn.net/jiuqiyuliang/article/details/45378065
1.基本
1.1Spring Framework 中有多少个模块,它们分别是什么?
- Spring 核心容器 – 该层基本上是 Spring Framework 的核心。它包含以下模块:
- Spring Core
- Spring Bean
- SpEL (Spring Expression Language)
- Spring Context
- 数据访问/集成 – 该层提供与数据库交互的支持。它包含以下模块:
- JDBC (Java DataBase Connectivity)
- ORM (Object Relational Mapping)
- OXM (Object XML Mappers)
- JMS (Java Messaging Service)
- Transaction
- Web – 该层提供了创建 Web 应用程序的支持。它包含以下模块:
- Web
- Web – Servlet
- Web – Socket
- Web – Portlet
- AOP – 该层支持面向切面编程
- Instrumentation – 该层为类检测和类加载器实现提供支持。
- Test – 该层为使用 JUnit 和 TestNG 进行测试提供支持。
- 几个杂项模块:
- Messaging – 该模块为 STOMP 提供支持。它还支持注解编程模型,该模型用于从 WebSocket 客户端路由和处理 STOMP 消息。
- Aspects – 该模块为与 AspectJ 的集成提供支持。
1.2Spring有哪些使用方法?
- 作为一个成熟的 Spring Web 应用程序。
- 作为第三方 Web 框架,使用 Spring Frameworks 中间层。
- 用于远程使用。
- 作为企业级 Java Bean,它可以包装现有的 POJO(Plain Old Java Objects)。
2.IOC控制反转
2.1什么是 Spring IOC 容器?
Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供。
2.2 什么是依赖注入?
In Dependency Injection, you do not have to create your objects but have to describe how they should be created. You don’t connect your components and services together in the code directly, but describe which services are needed by which components in the configuration file. The IoC container will wire them up together.
在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码中将组件和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。由 IoC 容器将它们装配在一起。
2.3有几种方式完成依赖注射?
1.构造函数注入
2.setter注入
3.接口注入
Spring中一般使用前两种
2.4setter注入和构造函数注入的区别
构造函数注入 | setter 注入 |
---|---|
没有部分注入 | 有部分注入 |
不会覆盖 setter 属性 | 会覆盖 setter 属性 |
任意修改都会创建一个新实例 | 任意修改不会创建一个新实例 |
适用于设置很多属性 | 适用于设置少量属性 |
2.5 spring中有多少种ioc容器
- BeanFactory - BeanFactory 就像一个包含 bean 集合的工厂类。它会在客户端要求时实例化 bean。
- ApplicationContext - ApplicationContext 接口扩展了 BeanFactory 接口。它在 BeanFactory 基础上提供了一些额外的功能。
2.6 区分 BeanFactory 和 ApplicationContext
BeanFactory | ApplicationContext |
---|---|
它使用懒加载 | 它使用即时加载 |
它使用语法显式提供资源对象 | 它自己创建和管理资源对象 |
不支持国际化 | 支持国际化 |
不支持基于依赖的注解 | 支持基于依赖的注解 |
2.7 IOC的优点
- 它将最小化应用程序中的代码量。
- 它将使您的应用程序易于测试,因为它不需要单元测试用例中的任何单例或 JNDI 查找机制。
- 它以最小的影响和最少的侵入机制促进松耦合。
- 它支持即时的实例化和延迟加载服务。
2.8 Spring IoC 的实现机制
Spring 中的 IoC 的实现原理就是工厂模式加反射机制
interface Fruit {
public abstract void eat();
}
class Apple implements Fruit {
public void eat(){
System.out.println("Apple");
}
}
class Orange implements Fruit {
public void eat(){
System.out.println("Orange");
}
}
class Factory {
public static Fruit getInstance(String ClassName) {
Fruit f=null;
try {
f=(Fruit)Class.forName(ClassName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class Client {
public static void main(String[] a) {
Fruit f=Factory.getInstance("io.github.dunwu.spring.Apple");
if(f!=null){
f.eat();
}
}
}
3.Beans
3.1. 什么是 spring bean?
- 它们是构成用户应用程序主干的对象。
- Bean 由 Spring IoC 容器管理。
- 它们由 Spring IoC 容器实例化,配置,装配和管理。
- Bean 是基于用户提供给容器的配置元数据创建。
3.2 spring提供的配置方式
- 基于 xml 配置
bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开头。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean">
<property name="name" value="Edureka"></property>
</bean>
- 基于注解配置
您可以通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件类本身,而不是使用 XML 来描述 bean 装配。默认情况下,Spring 容器中未打开注解装配。因此,您需要在使用它之前在 Spring 配置文件中启用它。例如:
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
- 基于 Java API 配置
-
Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。
- @Bean 注解扮演与
<bean />
元素相同的角色。
@Configuration 类允许通过简单地调用同一个类中的其他 @Bean 方法来定义 bean 间依赖关系。例如:
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}
3.3. spring 支持几种 bean scope?
-
Spring bean 支持 5 种 scope:
- Singleton - 每个 Spring IoC 容器仅有一个单实例。
- Prototype - 每次请求都会产生一个新的实例。
-
仅当用户使用支持 Web 的 ApplicationContext 时,最后三个才可用。
- Request - 每一次 HTTP 请求都会产生一个新的实例,并且该 bean 仅在当前 HTTP 请求内有效。
- Session - 每一次 HTTP 请求都会产生一个新的 bean,同时该 bean 仅在当前 HTTP session 内有效。
- Global-session - 类似于标准的 HTTP Session 作用域,不过它仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portlet 所共享。在 global session 作用域中定义的 bean 被限定于全局 portlet Session 的生命周期范围内。如果你在 web 中使用 global session 作用域来标识 bean,那么 web 会自动当成 session 类型来使用。
3.4 什么是 spring 装配
当 bean 在 Spring 容器中组合在一起时,它被称为装配或 bean 装配。 Spring 容器需要知道需要什么 bean 以及容器应该如何使用依赖注入来将 bean 绑定在一起,同时装配 bean。
3.5 自动装配有哪些方式?
Spring 容器能够自动装配 bean。也就是说,可以通过检查 BeanFactory 的内容让 Spring 自动解析 bean 的协作者。
自动装配的不同模式:
- no - 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。
- byName - 它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML 文件中由相同名称定义的 bean。
- byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名称匹配,则匹配并装配属性。
- 构造函数 - 它通过调用类的构造函数来注入依赖项。它有大量的参数。
- autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配。
局限性:
- 覆盖的可能性 - 您始终可以使用
<constructor-arg>
和<property>
设置指定依赖项,这将覆盖自动装配。 - 基本元数据类型 - 简单属性(如原数据类型,字符串和类)无法自动装配。
- 令人困惑的性质 - 总是喜欢使用明确的装配,因为自动装配不太精确。
4. 注解
4.1. 什么是基于注解的容器配置
不使用 XML 来描述 bean 装配,开发人员通过在相关的类,方法或字段声明上使用注解将配置移动到组件类本身。它可以作为 XML 设置的替代方案。例如:
Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。
- @Bean 注解扮演与 元素相同的角色。
- @Configuration 类允许通过简单地调用同一个类中的其他 @Bean 方法来定义 bean 间依赖关系。
例如:
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
}
}
4.2. 如何在 spring 中启动注解装配?
默认情况下,Spring 容器中未打开注解装配。因此,要使用基于注解装配,我们必须通过配置<context:annotation-config />
元素在 Spring 配置文件中启用它。
4.3. @Component, @Controller, @Repository, @Service 有何区别?
- @Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
- @Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。
- @Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。
- @Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。
4.4. @Required 注解有什么用?
@Required 应用于 bean 属性 setter 方法。此注解仅指示必须在配置时使用 bean 定义中的显式属性值或使用自动装配填充受影响的 bean 属性。如果尚未填充受影响的 bean 属性,则容器将抛出 BeanInitializationException。
示例:
public class Employee {
private String name;
@Required
public void setName(String name){
this.name=name;
}
public string getName(){
return name;
}
}
4.5. @Autowired 注解有什么用?
@Autowired 可以更准确地控制应该在何处以及如何进行自动装配。此注解用于在 setter 方法,构造函数,具有任意名称或多个参数的属性或方法上自动装配 bean。默认情况下,它是类型驱动的注入。
public class Employee {
private String name;
@Autowired
public void setName(String name) {
this.name=name;
}
public string getName(){
return name;
}
}
4.6. @Qualifier 注解有什么用?
当您创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。
例如,这里我们分别有两个类,Employee 和 EmpAccount。在 EmpAccount 中,使用@Qualifier 指定了必须装配 id 为 emp1 的 bean。
Employee.java
public class Employee {
private String name;
@Autowired
public void setName(String name) {
this.name=name;
}
public string getName() {
return name;
}
}
EmpAccount.java
public class EmpAccount {
private Employee emp;
@Autowired
@Qualifier(emp1)
public void showName() {
System.out.println(“Employee name : ”+emp.getName);
}
}
4.7. @RequestMapping 注解有什么用?
@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法。此注释可应用于两个级别:
- 类级别:映射请求的 URL
- 方法级别:映射 URL 以及 HTTP 请求方法
5. 数据访问
5.1. spring DAO 有什么用?
Spring DAO 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一种统一的方式工作。这使得用户容易在持久性技术之间切换。它还允许您在编写代码时,无需考虑捕获每种技术不同的异常。
5.2. 列举 Spring DAO 抛出的异常。
5.3. spring JDBC API 中存在哪些类?
- JdbcTemplate
- SimpleJdbcTemplate
- NamedParameterJdbcTemplate
- SimpleJdbcInsert
- SimpleJdbcCall
5.4. 使用 Spring 访问 Hibernate 的方法有哪些?
我们可以通过两种方式使用 Spring 访问 Hibernate:
- 使用 Hibernate 模板和回调进行控制反转
- 扩展 HibernateDAOSupport 并应用 AOP 拦截器节点
5.5. 列举 spring 支持的事务管理类型
Spring 支持两种类型的事务管理:
- 程序化事务管理:在此过程中,在编程的帮助下管理事务。它为您提供极大的灵活性,但维护起来非常困难。
- 声明式事务管理:在此,事务管理与业务代码分离。仅使用注解或基于 XML 的配置来管理事务。
5.6. spring 支持哪些 ORM 框架
- Hibernate
- iBatis
- JPA
- JDO
- OJB
6. AOP
6.1. 什么是 AOP?
AOP(Aspect-Oriented Programming), 即 面向切面编程, 它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角.
在 OOP 中, 我们以类(class)作为我们的基本单元, 而 AOP 中的基本单元是 Aspect(切面)
6.2. 什么是 Aspect?
aspect
由 pointcount
和 advice
组成, 它既包含了横切逻辑的定义, 也包括了连接点的定义. Spring AOP 就是负责实施切面的框架, 它将切面所定义的横切逻辑编织到切面所指定的连接点中.
AOP 的工作重心在于如何将增强编织目标对象的连接点上, 这里包含两个工作:
- 如何通过 pointcut 和 advice 定位到特定的 joinpoint 上
- 如何在 advice 中编写切面代码.
可以简单地认为, 使用 @Aspect 注解的类就是切面.
6.3. 什么是切点(JoinPoint)
程序运行中的一些时间点, 例如一个方法的执行, 或者是一个异常的处理.
在 Spring AOP 中, join point 总是方法的执行点。
6.4. 什么是通知(Advice)?
特定 JoinPoint 处的 Aspect 所采取的动作称为 Advice。Spring AOP 使用一个 Advice 作为拦截器,在 JoinPoint “周围”维护一系列的拦截器。
6.5. 有哪些类型的通知(Advice)?
- Before - 这些类型的 Advice 在 joinpoint 方法之前执行,并使用 @Before 注解标记进行配置。
- After Returning - 这些类型的 Advice 在连接点方法正常执行后执行,并使用@AfterReturning 注解标记进行配置。
- After Throwing - 这些类型的 Advice 仅在 joinpoint 方法通过抛出异常退出并使用 @AfterThrowing 注解标记配置时执行。
- After (finally) - 这些类型的 Advice 在连接点方法之后执行,无论方法退出是正常还是异常返回,并使用 @After 注解标记进行配置。
- Around - 这些类型的 Advice 在连接点之前和之后执行,并使用 @Around 注解标记进行配置。
6.6. 指出在 spring aop 中 concern 和 cross-cutting concern 的不同之处。
concern 是我们想要在应用程序的特定模块中定义的行为。它可以定义为我们想要实现的功能。
cross-cutting concern 是一个适用于整个应用的行为,这会影响整个应用程序。例如,日志记录,安全性和数据传输是应用程序几乎每个模块都需要关注的问题,因此它们是跨领域的问题。
6.7. AOP 有哪些实现方式?
实现 AOP 的技术,主要分为两大类:
- 静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
- 编译时编织(特殊编译器实现)
- 类加载时编织(特殊的类加载器实现)。
- 动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
- JDK 动态代理
- CGLIB
6.8. Spring AOP and AspectJ AOP 有什么区别?
Spring AOP 基于动态代理方式实现;AspectJ 基于静态代理方式实现。
Spring AOP 仅支持方法级别的 PointCut;提供了完全的 AOP 支持,它还支持属性级别的 PointCut。
6.9. 如何理解 Spring 中的代理?
将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目标对象和代理对象是相同的。
Advice + Target Object = Proxy
6.10. 什么是编织(Weaving)?
为了创建一个 advice 对象而链接一个 aspect 和其它应用类型或对象,称为编织(Weaving)。在 Spring AOP 中,编织在运行时执行。请参考下图:
7. MVC
7.1. Spring MVC 框架有什么用?
Spring Web MVC 框架提供 模型-视图-控制器 架构和随时可用的组件,用于开发灵活且松散耦合的 Web 应用程序。 MVC 模式有助于分离应用程序的不同方面,如输入逻辑,业务逻辑和 UI 逻辑,同时在所有这些元素之间提供松散耦合。
7.2. 描述一下 DispatcherServlet 的工作流程
DispatcherServlet 的工作流程可以用一幅图来说明:
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
- 向服务器发送 HTTP 请求,请求被前端控制器
DispatcherServlet
捕获。 DispatcherServlet
根据 -servlet.xml 中的配置对请求的 URL 进行解析,得到请求资源标识符(URI)。然后根据该 URI,调用HandlerMapping
获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象对应的拦截器),最后以HandlerExecutionChain
对象的形式返回。DispatcherServlet
根据获得的Handler
,选择一个合适的HandlerAdapter
。(附注:如果成功获得HandlerAdapter
后,此时将开始执行拦截器的 preHandler(...)方法)。- 提取
Request
中的模型数据,填充Handler
入参,开始执行Handler
(Controller
)。 在填充Handler
的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:- HttpMessageConveter: 将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息。
- 数据转换:对请求消息进行数据转换。如
String
转换成Integer
、Double
等。 - 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等。
- 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到
BindingResult
或Error
中。
- Handler(Controller)执行完成后,向
DispatcherServlet
返回一个ModelAndView
对象; - 根据返回的
ModelAndView
,选择一个适合的ViewResolver
(必须是已经注册到 Spring 容器中的ViewResolver
)返回给DispatcherServlet
。 ViewResolver
结合Model
和View
,来渲染视图。- 视图负责将渲染结果返回给客户端。
7.3. SpringMVC的组件有哪些?
(1)前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
(2)处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
Spring MVC 默认提供了4种 HandlerMapping的实现
- org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
通过配置请求路径和Controller映射建立关系,找到相应的Controller- org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping
通过 Controller 的类名找到请求的Controller。- org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
通过定义的 beanName 进行查找要请求的Controller- org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
通过注解 @RequestMapping("/userlist") 来查找对应的Controller在web.xml中注册配置DispatcherServlet 以及Mapping映射
<!--配置DispatcherServlet--> <servlet> <servlet-name>seckill-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC 需要配置的文件 applicationContext-dao.xml,applicationContext-service.xml,applicationContext-web.xml Mybites -> spring -> springMvc --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext-*.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>seckill-dispatcher</servlet-name> <!--默认匹配所有请求--> <url-pattern>/</url-pattern> </servlet-mapping>
在自建的applicationContext-web.xml中注册配置
<!--配置spring mvc--> <!--1,开启springmvc注解模式 a.自动注册DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter b.默认提供一系列的功能:数据绑定,数字和日期的format@NumberFormat,@DateTimeFormat c:xml,json的默认读写支持--> <mvc:annotation-driven/> <!--2.静态资源默认servlet配置--> <!-- 1).加入对静态资源处理:js,gif,png 2).允许使用 "/" 做整体映射 --> <mvc:default-servlet-handler/> <!--3:配置JSP 显示ViewResolver--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--4:扫描web相关的controller--> <context:component-scan base-package="com.nnngu.web"/>
在controller中加入注解
@Component @RequestMapping("/seckill")//url:模块/资源/{}/细分 public class SeckillController {......}
(3)处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
(4)处理器Handler(需要程序员开发)
(5)视图解析器 ViewResolver(不需要程序员开发)
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
(6)视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
7.4. 介绍一下 WebApplicationContext
WebApplicationContext 是 ApplicationContext 的扩展。它具有 Web 应用程序所需的一些额外功能。它与普通的 ApplicationContext 在解析主题和决定与哪个 servlet 关联的能力方面有所不同。
8 Mybaits
8.1 对Mybaits的理解?
1. mybatis配置
2. SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
3. mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
4. 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
5. 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
6. mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
7. Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
8. Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
9. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
8.2 连接池
1 dbcp
dbcp可能是使用最多的开源连接池,原因大概是因为配置方便,而且很多开源和tomcat应用例子都是使用的这个连接池。
这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
这个连接池的配置参见附件压缩包中的:dbcp.xml
使用评价:在具体项目应用中,发现此连接池的持续运行的稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性有所下降,此外不提供连接池监控。
2 c3p0
c3p0是另外一个开源的连接池,在业界也是比较有名的,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
使用评价:在具体项目应用中,发现此连接池的持续运行的稳定性相当不错,在大并发量的压力下稳定性也有一定保证,此外不提供连接池监控。
区别:c3p0有自动回收空闲连接功能
配置如下:
<!--配置数据库连接池-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--配置基本的数据库连接-->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<!--c3p0私有属性-->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!--关闭连接后不自动commit-->
<property name="autoCommitOnClose" value="false"/>
<!--获取连接超时时间-->
<property name="checkoutTimeout" value="1000"/>
<!--当获取连接失败时的重试次数-->
</bean>
8.3 SqlsessionFactory配置
<!--配置sqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据库连接池-->
<property name="dataSource" ref="dataSource"/>
<!--配置mybatis全局配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--配置entity包,也就是实体类包,自动扫描,用于别名配置-->
<property name="typeAliasesPackage" value="com.nnngu.entity"/>
<!--配置需要扫描的mapper.xml文件-->
<property name="mapperLocations" value="classpath*:com.nnngu.dao/*.xml"/>
</bean>
<!--配置mapper接口包,动态实现mapper接口,注入到Spring容器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入sqlSessionFactory,请注意不要使用sqlSessionFactoryBean,否则会出现注入异常-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--给出要扫描的mapper接口-->
<property name="basePackage" value="com.nnngu.dao" />
</bean>
8.4 mybatis与hibernate的区别?
1. 简介
Hibernate:Hibernate是当前最流行的ORM框架之一,对JDBC提供了较为完整的封装。Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL的自动生成和执行。
Mybatis:Mybatis同样也是非常流行的ORM框架,主要着力点在于 POJO 与 SQL 之间的映射关系。然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定 POJO 。相对Hibernate“O/R”而言,Mybatis 是一种“Sql Mapping”的ORM实现。
2. 开发速度
难易度
Hibernate的真正掌握要比Mybatis困难,Hibernate比mybatis更加重量级一些。
Mybatis框架相对简单很容易上手,但也相对简陋些。
开发工作量
Mybatis需要我们手动编写SQL语句,回归最原始的方式,所以可以按需求指定查询的字段,提高程序的查询效率。
Hibernate也可以自己写SQL语句来指定需要查询的字段,但这样破坏了Hibernate封装以及简洁性。
3. 数据库移植性
Mybatis由于所有SQL都是依赖数据库书写的,所以扩展性,迁移性比较差。
Hibernate与数据库具体的关联都在XML中,所以HQL对具体是用什么数据库并不是很关心。
4. 缓存机制对比
相同点
Hibernate和Mybatis的二级缓存除了采用系统默认的缓存机制外,都可以通过实现你自己的缓存或为其他第三方缓存方案,创建适配器来完全覆盖缓存行为。
不同点
Hibernate的二级缓存配置在SessionFactory生成的配置文件中进行详细配置,然后再在具体的表-对象映射中配置是那种缓存。
MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。
两者比较
因为Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。而MyBatis在这一方面,使用二级缓存时需要特别小心。如果不能完全确定数据更新操作的波及范围,避免Cache的盲目使用。否则,脏数据的出现会给系统的正常运行带来很大的隐患。
5. 两者对比总结
两者相同点
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。如下图所示:
Hibernate和MyBatis都支持JDBC和JTA事务处理。
Hibernate优势
Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。
Mybatis优势
MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
MyBatis容易掌握,而Hibernate门槛较高。
一句话总结
在博文的结尾,我们将Mybatis和Hibernate之间的区别自个用六个词做总结:
Mybatis:小巧、方便、高效、简单、直接、半自动化
Hibernate:强大、方便、高效、复杂、间接、全自动化
8.6 #{}和${}
的区别是什么?
#{}
解析传递进来的参数数据- ${}对传递进来的参数原样拼接在SQL中
#{}
是预编译处理,${}是字符串替换。- 使用#{}可以有效的防止SQL注入,提高系统安全性。
8.7 当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>
select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};
</select>
第2种: 通过<resultMap>
来映射字段名和实体类属性名的一一对应的关系
<select id="getOrder" parameterType="int" resultMap="orderresultmap">
select * from orders where order_id=#{id}
</select>
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
<!–用id属性来映射主键字段–>
<id property=”id” column=”order_id”>
<!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>
<result property = “orderno” column =”order_no”/>
<result property=”price” column=”order_price” />
</reslutMap>