You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring2.5+Hibernate3.3项目:让LocalSessionFactoryBean强制数据库连接只读

嘿,针对你的Spring 2.5 + Hibernate 3.3遗留项目要加只读报表库的需求,我给你整理了一套完全适配你技术栈的可行方案,一步步来:

实现步骤

1. 配置报表库的只读ComboPooledDataSource

首先给报表复制库单独配置一个数据源,核心是把连接全局设为只读——C3P0的ComboPooledDataSource可以通过setReadOnly(true)实现,这样从这个池里拿的所有连接默认都是只读状态,从根源上避免误写操作。

XML配置示例:

<bean id="reportDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <!-- 报表库JDBC基础配置 -->
    <property name="driverClass" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUrl" value="jdbc:mysql://report-db-host:3306/your_db?useUnicode=true&amp;characterEncoding=utf8" />
    <property name="user" value="report_user" />
    <property name="password" value="report_pass" />
    
    <!-- 核心:强制连接只读 -->
    <property name="readOnly" value="true" />
    
    <!-- C3P0连接池参数按需调整 -->
    <property name="initialPoolSize" value="5" />
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="20" />
    <property name="acquireIncrement" value="5" />
    <property name="maxIdleTime" value="1800" />
</bean>

2. 配置第二个LocalSessionFactoryBean

为报表库单独创建SessionFactory,关联上面的只读数据源,同时可以针对报表查询做些优化,比如关闭不必要的二级缓存、设置会话默认只读等。

XML配置示例:

<bean id="reportSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="reportDataSource" />
    
    <!-- 只加载报表相关的实体映射,避免全量加载浪费资源 -->
    <property name="mappingResources">
        <list>
            <value>com/yourcompany/model/SalesReport.hbm.xml</value>
            <value>com/yourcompany/model/UserStats.hbm.xml</value>
        </list>
    </property>
    
    <!-- Hibernate配置属性 -->
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.show_sql">false</prop>
            <!-- 双重保障:设置Hibernate会话默认只读 -->
            <prop key="hibernate.connection.read_only">true</prop>
            <!-- 报表查询不需要缓存的话直接关闭,提升性能 -->
            <prop key="hibernate.cache.use_second_level_cache">false</prop>
            <prop key="hibernate.cache.use_query_cache">false</prop>
        </props>
    </property>
</bean>

3. 配置报表库的专属事务管理器

因为是只读库,事务管理器要绑定报表SessionFactory,同时全局设置事务属性为只读,避免不必要的事务开销。

XML配置示例:

<!-- 报表库的Hibernate事务管理器 -->
<bean id="reportTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="reportSessionFactory" />
</bean>

<!-- 报表事务拦截器:所有报表方法默认只读事务 -->
<bean id="reportTransactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="reportTransactionManager" />
    <property name="transactionAttributes">
        <props>
            <prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <!-- 特殊方法可单独配置 -->
        </props>
    </property>
</bean>

<!-- 自动代理报表相关DAO,应用事务拦截器 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
        <list>
            <value>*ReportDao</value>
            <!-- 匹配所有报表DAO的Bean名称 -->
        </list>
    </property>
    <property name="interceptorNames">
        <list>
            <value>reportTransactionInterceptor</value>
        </list>
    </property>
</bean>

4. 实现报表专用DAO

创建报表相关的DAO时,注入reportSessionFactory而非原主库的SessionFactory,确保操作的是只读库。

Java代码示例:

public class SalesReportDao extends HibernateDaoSupport {

    // 注入报表专属SessionFactory
    @Override
    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    public List<SalesReport> queryMonthlySales(int year, int month) {
        String hql = "from SalesReport where year = :year and month = :month";
        return getHibernateTemplate().findByNamedParam(hql,
            new String[]{"year", "month"},
            new Object[]{year, month});
    }
}

对应的XML配置:

<bean id="salesReportDao" class="com.yourcompany.dao.SalesReportDao">
    <property name="sessionFactory" ref="reportSessionFactory" />
</bean>

关键注意事项

  • 双重只读保障:数据源层面+Hibernate会话层面+事务拦截器三重限制,最大程度杜绝误写操作。
  • 映射隔离:报表SessionFactory只加载必要的实体映射,减少内存占用和初始化时间。
  • 连接池隔离:两个数据源完全独立,避免主库和报表库的连接池互相影响,按需调整各自参数。
  • 避免跨库事务:Spring2.5对跨库事务支持有限,尽量保证报表操作和主库操作完全隔离。

内容的提问来源于stack exchange,提问作者offbyone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:52:10