Spring
概述
分层的JavaSE/EE (一栈式) 轻量级开源框架。
- 表现层:Spring MVC
- 持久层:JdbcTemplate、ORM框架整合
- 业务层:IoC、AOP、事务控制
核心思想
- IoC(Inverse of Control 反转控制): 将对象创建权利交给Spring工厂进行管理
- AOP(Aspect Oriented Programming 面向切面编程),基于动态代理的功能增强方式
优点
方便解耦,简化开发
- Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理
AOP编程的支持
- Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
声明式事务的支持
- 通过配置就可以完成对事务的管理,无需手动编程
方便程序的测试
- Spring对Junit4支持,可以通过注解方便的测试Spring程序
方便集成各种优秀框架
- Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis、Quartz等)的直接支持
降低JavaEE API的使用难度
- Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
配置
环境搭建
- 核心包
- beans
- core
- context
- expression
- 日志包
- apache common-logging
- log4j
核心配置文件
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="" class=""/> </beans>
装配bean的四种方式
无参构造(最常用)
<bean id="beanid" class="bean"/>
静态工厂(某些框架初始化使用)
<bean id="beanid" class="factory" factory-method=""/> 可以在实例化的方法中书写业务
实例工厂(某些框架初始化使用)
<bean id="factoryid" class="factory"/> <bean id="beanid" factory-bean="factoryid" factory-method=""/>
FactoryBean方式(spring底层使用)
public class MyFactoryBean implements FactoryBean<Bean>{ public Object getObject()throws Exception{ return new Bean(); } } <bean id="beanid" class="factory"/>
BeanFactory和FactoryBean的区别
- BeanFactory(ApplicationContext):是一个工厂(其实是构建了一个spring上下文的环境,容器),用来管理和获取Bean对象
- FactoryBean:是一个Bean生成工具,是用来获取一种类型对象的Bean,是构造Bean实例的一种方式
IOC
通过工厂获取bean
- 读取配置文件,获取工厂
- 配置文件在src目录下
- ApplicationContext context=new ClassPathXmlApplicationContext(“applicationContext.xml”)
- 配置文件在WEB-INF目录下
- new FileSystemXmlApplicationContext(“applicationContext.xml”)
- 生成bean
- context.getBean(“id”);与xml中注册的id或name一致
- context.getBean(Bean.class)如果注册了多个Bean,spring找不到唯一对象报错
DI依赖注入
- 在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件中
- 对Bean对象的属性赋值
依赖注入的方式
接口注入(spring不支持)
构造器参数注入
- 配置文件
<bean name="" class=""> <constructor-arg name="" index="0" type="java.lang.Double" ref="" value=""/>定位属性可以联合使用 赋值属性只能存在一个 <constructor-arg name=""> <value>value</value> </constructor-arg> </bean>
- 配置文件中参数个数必须与构造方法一致
setter方法注入
- 配置文件
<bean name="" class=""> <property name="" ref=""/> <property name=""> <ref bean=""/> </property> </bean>
- 必须有无参构造
- 相应属性有setter方法
- 属性名可以与标签中name不一致,但setter方法必须与标签一致
p名称空间的使用
引入名称空间
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
将子标签转化为p属性
<bean name="" class="" p:username="" p:car-ref=""/>
ApplicationContext
- 父接口BeanFactory
Bean的作用域
singleton
- 在一个spring容器中,对象只有一个实例。默认值
Spring使用ThreadLocal解决线程安全问题 对于实体bean一般通过方法参数的的形式传递(参数是局部变量),所以多线程之间不会有影响 有的地方对于有状态的bean直接使用prototype原型模式来进行解决 对于使用bean的地方可以通过new的方式来创建
- prototype
- 在一个spring容器中,存在多个实例,每次getBean 返回一个新的实例
- request
- 每次请求创建一个实例,仅适用于WebApplicationContext环境
- session
- 每个Session创建一个实例,仅适用于WebApplicationContext环境
- globalSession
- 用于Porlet环境,仅适用于WebApplicationContext环境
Bean的生命周期
通过 init-method属性 指定初始化后的调用方法
通过 destroy-method属性 指定销毁对象前的方法
<bean name="" scope="singleton" class="" init-method="" destroy-method=""/>
- 销毁方法执行的条件
- singleton类型的bean才可以手动销毁
- 手动关闭容器
(ClassPathXmlApplicationContext)context.close();
- 销毁方法执行的条件
singleton第一次getBean时工厂实例化并加载所有配置,工厂关闭时销毁
- prototype每次getBean时实例化,destroy方法无法由工厂调用
Bean类的初始化
- init方法
- 完全解耦,init方法专门书写初始化代码,构造器只用来构造对象
- 直接赋值
- 耦合性最强,一般用于给默认值
- 在构造器中初始化
- 使用有参构造来初始化,new的时候直接初始化,但有点耦合
spEL表达式
基本语法#{}
- 引用Bean(具体对象) #{beanid}
* 可以替代ref属性 - 引用Bean的属性#{beanId.属性}
- 调用Bean的方法{beanId.方法(参数)}
集合类型注入
list集合
<bean name="" class=""> <property name="list"> <list> <value>aa</value> <value>bb</value> </list> </property> </bean>
set集合
<bean name="" class=""> <property name="list"> <set> <value>aa</value> <value>bb</value> </set> </property> </bean>
map集合
<bean name="" class=""> <property name="list"> <set> <entry key="" key-ref="" value="" value-ref=""/>value与value-ref不能同时存在 <entry key="">bb</value> </set> </property> </bean>
properties集合
<property name="properties"> Properties集合只支持字符串属性键值对 <props> <prop key="c">cc</prop> <prop key="d">dd</prop> </props> </property>
配置文件分开管理
主配置文件中包含其他的配置文件
<import resource="applicationContext2.xml"/>
工厂创建的时候加载多个配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "applicationContext.xml","applicationContext2.xml");
注解开发
基本流程
搭建环境配置
spring-aop的jar包
约束
xmlns:context="http://www.springframework.org/schema/context" schemalocation:"http://www.springframework.org/schema.context http://www.springframework.org/schema.context/spring-context.xsd"
配置注解扫描
<context:component-scan base-package="com.xxx.spring.test"/>
在类上添加注解
常用注解
- @Component
- @Controller
- @Service
- @Repository
- 属性注入(可以不提供set方法)
- @Value注入普通类型
- @Autowired
- 默认按类型装配
- @Qualifier按名称注入
- @Resource
- 相当于AutoWired和Qualifier同时使用
- bean作用范围注解
- @Scope
- singleton
- prototype
- 生命周期
- @PostConstruct表示init方法
- @PreDestroy表示destroy方法
JUNIT测试
导包
spring-test.jar spring-test-3.2.0.RELEASE.jar
@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration(locations=”classpath:applicationContext.xml”)
在测试类中注入 测试对象
- @AutoWired
最后的test类应该用注解配置并进行ioc注入,xml配置不生效
AOP开发
概述
- 横向抽取机制,取代了传统纵向继承体系重复性代码的编写方式(性能监视、事务管理、安全检查、缓存,日志记录等)。
- 从父类继承的方法也可以加强
术语
- joinpoint连接点
- pointcut切入点
- advice通知
- introduction引介
- target
- weaving织入
- spring采用动态代理织入
- AspectJ采用编译期织入和类装载期织入
- proxy
- aspect
实现原理
- JDK动态代理
- 接口代理,spring优先使用
- cglib动态代理
- 生成子类代理
基本流程
环境搭建
导入包 spring-aop-4.2.4.RELEASE.jar com.springsource.org.aopalliance-1.0.0.jar spring-aspects-4.2.4.RELEASE.jar com.springsource.org.aspectj.weaver-1.0.0.jar 引入约束 xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemalocation="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop/spring-aop.xsd
配置切面类
- 编写切面类
- 编写配置文件
<bean name="aspectid" class="" /> <aop:config name="properties"> 配置切入点 <aop:pointcut expression="execution()" id="pointcut"/> 全局切入点,针对所有切面生效 execution配置:[public] * cn.xxx.spring.dao.*.* (..) 修饰符 返回值 包名 类名 方法名 参数 配置切面 <aop:aspect ref="aspectid"> <aop:pointcut expression="execution()" id="pointcut"/> 仅针对当前生效 <aop:before method="before" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
切入点语法
- bean(bean Id/bean name)
- execution(<访问修饰符>?<返回类型>空格<方法全名>(<参数>)<异常>?)
- within(包.类)
- within(cn.itcast.spring..*) 增强spring包和子包所有bean“所有方法 ”
- this(完整类型)/target(完整类型)
- this(cn.itcast.spring.a_jdkproxy.CustomerServiceImpl) 增强类型所有方法(对代理对象有效)
- target(cn.itcast.spring.a_jdkproxy.CustomerServiceImpl) 增强类型所有方法(对源对象有效)
- 通配符
- *:匹配任何数量字符;
- ..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数
- +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边
- 多个切入点表达式用||连接
通知类型
前置通知
<aop:before method="before" pointcut-ref="pointcut"/> 如果写pointcut,值为execution表达式
后置通知
public void after(Jointpoint joinpoint,Object object){object是invoke的返回值 //... } <aop:after-returning method="after" after-returning="object" pointcut-ref="pointcut"/>
环绕通知
public Object after(ProceedingJointpoint joinpoint) throws Throwable{ //object是invoke的返回值 //... Object obj joinpoint.proceed(); //... return obj; } <aop:around method="around" pointcut-ref="pointcut"/>
异常通知
public void afterThrowing(Jointpoint joinpoint,Throwable ex){object是invoke的返回值 //... } <aop:after throwing="after" throwing="ex" pointcut-ref="pointcut"/>
最终通知
public void afterThrowing(Jointpoint joinpoint){object是invoke的返回值 //... } <aop:after throwing="after" throwing="ex" pointcut-ref="pointcut"/>
注解aop开发
编写pojo类作为增强类
- 添加@Aspect注解
- 交给spring管理
- @Component(“myAspect”)
在通知方法上添加
- @before
- @afterReturning
- @after
- @around
- @afterThrowing
- @declaredParents
开启AepectJ注解自动代理
<aop:aspectj-autoproxy/> 自动扫描带有@aspect注解的bean,将其作为增强aop配置,相当于<aop:config> <aop:aspectj-autoproxy proxy-target-class="true"/> 调用cglib机制生成代理
使用@pointcut定义切入点
- aspect类中书写方法
@pointcut("bean(*)") public void myAspect(){}
- 具体方法上定义要使用的切入点
@before(value="com.it.spring.Myaspect.myAspect()") //写方法的全路径,用于引入其他类中定义的切入点 public void before(){}
- 方法上直接定义切入点
@before("bean(*)") //内部参数直接写表达式,该表达式仅针对当前方法生效 public void before(){} @before("bean(*)||mypointcut()") //对多个切入点生效,mypointcut()应该是本类的方法 public void before(){}
对dao层的aop
管理连接池
内置连接池
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="root"/> <property name="password" value="123"/> <property name="url" value="jdbc:mysql:///crm"/> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> </bean>
c3p0连接池
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="root"/> <property name="password" value="123"/> <property name="jdbcUrl" value="jdbc:mysql:///crm"/> <property name="driverClass" value="com.mysql.jdbc.Driver"/> </bean>
将连接池注入template
<bean id="template" class="org.springframework.jdbc.coreJdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="accountDAO" class="test.AccountDAO"> <property name="template" ref="template"/> </bean>
引入外部属性文件
<context:property-placeholder location="classpath:db.properties"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="driverClass" value="${jdbc.password}"/> </bean>
继承DAOSupport
public final void setDataSource(DataSource dataSource){ if(..){ this.jdbctemplate=createTemplate(dataSource); initTemplateConfig(); } }
编写配置文件,注入注入jdbcTemplate
<bean id="accountDAO" class="test.AccountDAO"> <property name="dataSource" ref="dataSource"/> </bean>
JDBC模板
update(String sql, Object... args)
queryForObject(String sql, Class<T> requiredType, Object... args)
query(String sql, RowMapper<T> rowMapper, Object... args)
事务管理
事务管理器
- 接口PlatformTransactionManager
- 实现
- DataSourceTransactionManager
- HibernateTransactionManager
事务定义
- 接口TransactionDefinition
- 方法
- getIsolationLevelt隔离级别
- getPropagationBehavior传播行为
- getTimeout超时时间
- isReadOnly 只读
事务状态
- 接口TransactionStatus
- 方法
- flush()
- hasSavepoint()
- isCompleted()
- isNewTransaction()
- isRollbackOnly()
- setRollbackOnly()
编程式事务
- TransactionTemplate
声明式事务
- 使用XML或注解配置声明式事务
- Spring的声明式事务通过AOP实现
配置文件方式
引入约束
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
配置对特定持久层框架使用的事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.dataSource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> 这是用来向切面类TransactionInterceptor注入的属性
配置通知
<bean id=”transactionInterceptor” class=” org.springframework.transaction.interceptor.TransactionInterceptor”>不常用
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="transfer" isolation="DEFAULT" timeout="-1" rollback-for="" non-rollback-for=""/> <!-- transfer后的方法按照这一行的配置进行增强,其他的按照默认方式增强(默认每个操作为一个事务,相当于没增强)--> </tx:attributes> </tx:advice>
配置切面
<aop:config name="properties"> <!-- 配置切入点--> <aop:pointcut expression="execution()" id="pointcut"/> <!-- 配置切面--> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/> <!-- 默认使用TransactionInterceptor的intercept方法 相当于 <aop:aspect ref="aspectid"><aop:before method="before" pointcut-ref="pointcut"/></aop:aspect>--> </aop:config>
注解方式
开启注解扫描
配置注解驱动事务管理
- 注册事务管理注解
<tx annotation-drivern transaction-manager="transactionManager"/> 当注册的事务管理器id或name为transactionManager <tx annotation-drivern />
- 配置对特定持久层框架使用的事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.dataSource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
在需要管理事务的方法或者类上面 添加@Transactional 注解
- 事务定义信息在注解中直接配置
类上的@Transactional 注解为所有本类public方法包装事务
方法上的@Transactional 注解覆盖本类上的@Transactional 注解
xml与注解的对比
XML方式 ,使用通配符集中式维护
<tx:method name="transfer*" isolation="default" timeout="-1" rollback-for="" non-rollback-for=""/> <tx:method name="save*" isolation="default" timeout="-1" rollback-for="" non-rollback-for=""/> <tx:method name="update*" isolation="default" timeout="-1" rollback-for="" non-rollback-for=""/> <tx:method name="find*" isolation="default" timeout="-1" rollback-for="" non-rollback-for=""/>
事务传播行为
- 使用一个事务
- PROPAGATION_REQUIRED(默认值,如果当前没有事务则创建一个 事务)
- PROPAGATION_SUPPORTS(使用当前事务,如果当前没有事务则不使用)
- PROPAGATION_MANDATORY(使用当前事务,当前没有事务则抛异常)
- 使用独立事务
- PROPAGATION_REQUIRES_NEW(如果有新事务,挂起当前事务,开启新事务)
- PROPAGATION_NOT_SUPPORTED(非事务方式运行,挂起当前事务)
- PROPAGATION_NEVER(非事务方式运行,如果有当前事务抛异常)
- 嵌套事务
- PROPAGATION_NESTE
- 当A执行之后,就会在这个位置设置一个保存点.如果B没有问题.执行通过.如果B出现异常,运行客户根据需求回滚
SSH的整合
环境搭建
jar包导入
- struts2
struts2-core-2.3.32.jar xwork-core-2.3.32.jar ognl-3.0.19.jar asm-3.3.jar asm-commons-3.3.jar asm-tree-3.3.jar commons-fileupload-1.3.2.jar commons-io-2.2.jar commons-lang3-3.2.jar freemarker-2.3.22.jar javassist-3.11.0.GA.jar
- hibernate
antlr-2.7.7.jar dom4j-1.6.1.jar geronimo-jta_1.1_spec-1.1.1.jar hibernate-commons-annotations-5.0.1.Final.jar hibernate-core-5.0.7.Final.jar hibernate-jpa-2.1-api-1.0.0.Final.jar jandex-2.0.0.Final.jar javassist-3.18.1-GA.jar已经导入 jboss-logging-3.3.0.Final.jar
- 日志包
log4j-1.2.16.jar
- 数据库驱动
mysql-connector-java-5.1.42-bin.jar
- 连接池
c3p0-0.9.2.1.jar 用spring全整合hibernate时不需要 mchange-commons-java-0.2.3.4.jar hibernate-c3p0-5.0.7.Final.jar
- spring
核心包 spring-core-3.2.0.RELEASE.jar spring-beans-3.2.0.RELEASE.jar spring-expression-3.0.5.RELEASE.jar spring-context-3.0.5.RELEASE.jar 日志 com.springsource.org.apache.commons.logging-1.1.1.jar log4j-1.2.16.jar已经导入 aop实现 spring-aop-4.2.4.RELEASE.jar spring-aspects-4.2.4.RELEASE.jar aop第三方 com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar 事务与连接 spring-jdbc-4.2.4.RELEASE.jar spring-tx-4.2.4.RELEASE.jar 整合orm框架(hibernate) spring-orm-4.2.4.RELEASE.jar 整合web资源 spring-web-4.2.4.RELEASE.jar 单元测试 spring-test-4.2.4.RELEASE.jar
配置文件
hibernate.cfg.xml log4j.properties applicationContext.xml web.xml struts.xml
整合web
配置核心监听器
- 启动tomcat时加载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>
src下spring配置文件头
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
配置过滤器
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("menu.jsp...............");
HttpServletRequest req = (HttpServletRequest) servletRequest;
ApplicationContext ac =
WebApplicationContextUtils.getWebApplicationContext(req.getSession().getServletContext());
CategoryService categoryService = (CategoryService) ac.getBean("categoryService");
List<Category> list = categoryService.findCategorysByCriteria(DetachedCriteria.forClass(Category.class));
req.setAttribute("category_list", list);
filterChain.doFilter(req, servletResponse);
}
配置Action
引入插件包
struts2-spring-plugin.jar
- 插件包下struts-plugin.xml生效
- 覆盖default-struts.xml中常量
<constant name="struts.objectFactory" value="spring">
- 修改struts的对象工厂为 spring (StrutsSpringObjectFactory)
- struts-core.jar 中default.properties中struts.objectFactory属性也被覆盖为spring
- struts.objectFactory.spring.AutoWire被激活,默认按名称注入bean(可以手动修改为type等)
创建action
Action由struts创建
StrutsSpringObjectFactory自行创建action
- 不能被spring管理
默认多实例
Action由spring创建
applicationContext.xml中配置bean类,类型为多例
<bean id="bookAction" class="cn.itcast.ssh.web.action.BookAction" scope="prototype"> <!-- 主动注入service --> <property name="bookService" ref="bookService"></property> </bean>
- struts.xml中配置action的类名为bean的id,由spring的ioc容器提供action
<action name="book_*" class="bookAction" method="{1}"></action>
- applicationContext.xml中没有配置bean类,自行new一个action
action中注入service (spring与struts的整合)
- 提供setter方法
- Action由struts创建
- StrutsSpringObjectFactoryt工厂根据名称和set方法自动装配service
- Action由spring创建
- 需要在bean类中配置property属性
配置service
- service中注入dao
- 配置事务管理
- 配置事务管理器(必须)
- 写操作需要配置事务管理器并在通知中将read-only属性配置为false
- 读操作不受影响
- 开启注解事务管理
- 添加注解
配置DAO
注入SessionFactory
继承HibernateDaoSupport
dao中注入SessionFactory(Spring与hibernate的整合)
- 不带hibernate配置文件
- spring中配置连接池(为了其他整合的框架使用)
- 配置hibernate属性
- 引入映射文件
<!-- 加载外部属性文件 --> <context:property-placeholder location="classpath:db.properties"/> <!-- 数据源 :c3p0--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 注意不同的数据源,属性不一定一样 --> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Mysql5Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <property name="mappingResources"> <list> <value>cn/it/spring/Book.hbm.xml</value> <value></value> <value></value> <value></value> </list> </property> </bean>
带hibernate配置文件
在spring配置文件中配置SessionFactory
- 改写DAO,注入SessionFactory
<!--1. 零障碍整合:Hibernate的核心配置文件独立 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!--注入hibernate.cfg.xml 在spring的所有配置中,只要属性名字带有location的单词,那么路径必须加上classpath: configLocation属性用来加载hibernate核心配置文件的位置--> <property name="configLocation" value="classpath:hibernate.cfg.xml"/> </bean>
调用模板
- getHibernateTemplate()
命名查询
HQL命名查询
- 对Hql查询的优化
- 将Hql语句从代码中剥离出来
在hbm.xml中配置Hql语句 <query name="Book.findBookByName">from Book where name like ?</query> getHibernateTemplate().findByNamedQuery(queryName, values);
SQL命名查询
<sql-query name="selectEmpByJob"> <return alias="e" class="entity.Emp"></return> //此处不配置则无法完成自动封装 select {e.*} from EMP e where e.job=:job </sql-query> <sql-query name="selectBlogsByContent"> <return alias="blog" class="cn.enjoylife.hibernate.bean.Blog" > <return-property name="id" column="id"></return-property> <return-property name="title" column="title"></return-property> <return-property name="content" column="content"></return-property> <return-property name="blogAuthorId" column="blogAuthorId"></return-property> </return> SELECT t.id "id", t.title "title", t.content "content", t.BLOG_AUTHOR_ID "blogAuthorId" FROM blog t WHERE t.content LIKE :contentPattern </sql-query> <sql-query name="selectBlogsByContent"> <return-scalar column="id" type="integer"/> <return-scalar column="title" type="string"/> <return-scalar column="content" type="string"/> SELECT t.id "id", t.title "title", t.content "content" FROM blog t WHERE t.content LIKE :contentPattern </sql-query>
配置延迟加载
原因
- 业务层查询数据返回后,session关闭, 表现层关联延迟数据,无法初始化
解决
- 配置为立即加载 lazy=false(占用资源)
- Service方法返回前, 对延迟数据进行初始化(增加代码量)
List<Employee> list = dao.findAll (); for(Employee e : list ){ Hibernate.initialize(e.getDepartment() ); }
- OpenSessionInView 机制
- OpenSessionInViewFilter配置在struts2核心过滤器之前
- session在web层创建,web层销毁
- 副作用1:没有被事务管理的方法, OpenSessionInViewFilter 会将这些方法的事务变为 readOnly (配置事务的方法不受影响)
- 副作用1:当页面超出缓冲区大小,渲染模板分次向response.getWriter中写数据,导致数据库连接被占用时间过长
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>过滤所有资源
<url-pattern>*.action</url-pattern>过滤所有action
<url-pattern>/customer_list.action</url-pattern>过滤指定action
</filter-mapping>