在经典的SSH(Struts + Spring + Hibernate)框架整合项目中,数据库连接是整个应用数据持久化的基石,其核心思想是利用Spring的IoC(控制反转)容器来统一管理Hibernate的核心组件,从而实现解耦和简化配置,整个连接过程并非由单一框架完成,而是三者各司其职,协同工作的结果。
核心角色分工
要理解SSH如何连接数据库,首先要明确每个框架在其中的角色。
框架 | 主要职责 | 在数据库连接中的角色 |
---|---|---|
Hibernate | 对象关系映射(ORM)框架 | 负责将Java对象(POJO)与数据库表进行映射,并最终执行SQL语句与数据库交互,它是直接与数据库“对话”的组件。 |
Spring | 轻量级容器,整合框架 | 作为“总指挥”,负责管理Hibernate的SessionFactory ,配置数据源(连接池),并统一处理事务,它将数据库连接资源注入到需要它的DAO层。 |
Struts | Web层MVC框架 | 负责处理用户请求和页面响应,它不直接接触数据库,而是调用Spring管理的业务逻辑层(Service)来完成操作。 |
由此可见,数据库连接的核心配置和管理工作,主要落在Spring和Hibernate身上。
关键配置步骤
SSH项目连接数据库的配置主要集中在Spring的配置文件(通常是applicationContext.xml
)中,以下是几个关键步骤:
配置数据源
数据源是数据库连接池的抽象,它管理着多个数据库连接,避免了频繁创建和销毁连接所带来的性能开销,在SSH项目中,通常使用第三方连接池实现,如C3P0、DBCP或Druid。
在applicationContext.xml
中配置一个C3P0数据源的示例如下:
<!-- 配置C3P0数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8" /> <property name="user" value="your_username" /> <property name="password" value="your_password" /> <!-- 其他连接池配置,如最大连接数、初始连接数等 --> <property name="maxPoolSize" value="20"/> <property name="minPoolSize" value="5"/> </bean>
这段XML定义了一个ID为dataSource
的Bean,它封装了数据库连接所需的所有信息。
配置Hibernate SessionFactory
SessionFactory
是Hibernate的核心接口,负责创建和管理Session
对象(可以理解为一个数据库连接会话),在SSH整合中,我们不再使用Hibernate自己的hibernate.cfg.xml
文件,而是将SessionFactory
的配置权交给Spring。
通过Spring的LocalSessionFactoryBean
,我们可以将上一步配置的数据源注入进来,并指定Hibernate的特定属性和实体映射文件。
<!-- 配置Hibernate的SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource" /> <!-- 设置Hibernate相关属性 --> <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> </props> </property> <!-- 指定Hibernate映射文件的位置 --> <property name="mappingDirectoryLocations"> <list> <value>classpath:com/your/project/entity</value> </list> </property> </bean>
这样,Spring容器就完全接管了SessionFactory
的创建和生命周期管理。
配置事务管理
数据库操作必须在事务中进行,以保证数据的一致性,Spring提供了强大的声明式事务管理功能,它通过AOP(面向切面编程)的方式,让我们可以无感知地添加事务控制。
配置事务管理器,它需要一个数据源的引用:
<!-- 配置Spring的事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 启用基于注解的声明式事务 --> <tx:annotation-driven transaction-manager="transactionManager" />
配置完成后,我们只需在Service层的方法上添加@Transactional
注解,Spring就会自动为该方法开启、提交或回滚事务。
整合与使用
配置完成后,如何在DAO(数据访问对象)层使用呢?通过依赖注入,Spring会将我们配置好的SessionFactory
注入到DAO类中。
@Repository("userDao") public class UserDaoImpl implements UserDao { @Autowired private SessionFactory sessionFactory; @Override public User findById(Integer id) { // 从当前线程绑定的Session中获取Session Session session = sessionFactory.getCurrentSession(); return session.get(User.class, id); } }
当Service层调用findById
方法时,由于@Transactional
的存在,Spring会开启一个事务,并将一个Session
绑定到当前线程。sessionFactory.getCurrentSession()
正是获取了这个与事务绑定的Session
,方法执行完毕,事务自动提交,Session
也随之关闭。
小编总结流程
- 用户请求到达Struts的Action。
- Action调用Spring管理的Service层业务方法。
- Service层方法(通常带有
@Transactional
注解)调用DAO层数据访问方法。 - Spring检测到事务注解,通过事务管理器开启一个数据库事务,并将一个Hibernate
Session
绑定到当前线程。 - DAO层通过注入的
SessionFactory
获取当前线程的Session
,执行数据库操作。 - Service方法执行完毕,若无异常,Spring提交事务;若有异常,则回滚事务。
相关问答FAQs
Q1: 为什么需要Spring来管理Hibernate,不能直接在DAO中自己创建SessionFactory和Session吗?
A: 当然可以,但那样做会带来很多问题,直接在DAO中管理SessionFactory
会导致代码与Hibernate API强耦合,难以维护和测试,更重要的是,Spring的管理带来了巨大优势:第一,它统一管理了数据源和连接池,提高了性能和资源利用率;第二,它提供了强大的声明式事务管理,将事务代码与业务逻辑完全分离,极大简化了开发;第三,Spring的HibernateTemplate
或直接注入SessionFactory
的模式,封装了异常处理和资源关闭等繁琐操作,使DAO代码更加纯净。
Q2: 在SSH项目中,hibernate.cfg.xml
文件是不是完全没用了?
A: 在标准的SSH整合实践中,hibernate.cfg.xml
通常会被弃用,因为它的所有核心配置功能(如数据库连接信息、方言、映射文件等)都可以通过Spring的applicationContext.xml
来完成,将所有配置集中在Spring中,符合“单一配置源”的原则,便于统一管理和维护,如果你是在一个非Spring环境下单独使用Hibernate,或者出于某些历史原因,hibernate.cfg.xml
依然可以发挥作用,但在SSH整合中,它显得多余了。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复