如何正确覆盖Spring和Hibernate的BasicDataSource [英] How to correctly override BasicDataSource for Spring and Hibernate

查看:238
本文介绍了如何正确覆盖Spring和Hibernate的BasicDataSource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我在Spring中具有以下基本数据源:

Currently I have following basic data source in Spring:

<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost/test?relaxAutoCommit=true" />
    ...
</bean>

现在,我需要提供基于服务器环境(而非配置)的自定义数据源,为此,我需要根据某些条件计算driverClassNameurl字段.

Now I need to provide custom data source based on server environment (not config), for which I need to calculate driverClassName and url fields based on some condition.

我尝试覆盖createDataSource()方法:

public class MyDataSource extends BasicDataSource {

    @Override
    protected synchronized DataSource createDataSource() throws SQLException {
        if(condition) {
            super.setDriverClassName("com.mysql.jdbc.Driver");
            super.setUrl("jdbc:mysql://localhost/test?relaxAutoCommit=true");
        } else {
            //...
        }
        return super.createDataSource();
    }
}

这是可行的,但我注意到每次执行查询时都会调用createDataSource()(?),所以我宁愿将条件测试移到其他地方.

Which works, but I noticed that createDataSource() is getting called each time a query is executed(?), so I would rather move my condition testing elsewhere.

我尝试覆盖也起作用的setDriverClassName()setUrl(),并且从我所知道的只能被调用一次,但是然后我需要在Spring配置中提供一些值以触发这些设置器,因为它们没有被调用否则:

I tried overriding setDriverClassName() and setUrl() which also works and is getting called only once from what I can tell, but then I need to provide some values in Spring configuration in order to trigger those setters as they are not called otherwise:

<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="whatever" />
    <property name="url" value="whatever" />
    ...
</bean>

这看起来可能令人困惑.

which might look confusing.

有没有更好的解决方案?

Are there any better solutions?

推荐答案

无需扩展BasicDataSource.继承是最强的耦合形式,除非您有真正的理由使用它,否则应避免使用它.

There is no need to extend BasicDataSource. Inheritance is the strongest form of coupling and should be avoided unless you have a real reason to use it.

您有两个选择:

  • 创建一个包装器(使用合成代替继承)

  • Create a wrapper (use composition instead of inheritance)

public class MyDataSource implements DataSource {
    private BasicDataSource target = new BasicDataSource();
    public MyDataSource() {
        if (condition) {
            target.setDriverClassName("com.mysql.jdbc.Driver");                
            target.setUrl("jdbc:mysql://localhost/test?relaxAutoCommit=true"); 
        } else { ... }
    }
    public Connection getConnection() {
        return target.getConnection();
    }
    ... etc ...
}

  • 创建工厂(由于仅需要自定义对象的创建阶段,因此无需控制对象的整个生命周期).

  • Create a factory (since you need to customize only the creation phase of the object, you don't need to control the whole lifetime of it).

     public class MyDataSourceFactory {
        public DataSource createDataSource() {
            BasicDataSource target = new BasicDataSource();
            if (condition) {
                target.setDriverClassName("com.mysql.jdbc.Driver");                
                target.setUrl("jdbc:mysql://localhost/test?relaxAutoCommit=true"); 
            } else { ... }
            return target;
        }
    }
    

    .

    <bean id = "factory" class = "MyDataSourceFactory" />
    <bean id = "dbcpDataSource" 
         factory-bean = "factory" factory-method = "createDataSource">
         <property ... />
    </bean>
    

  • 编辑:请注意,您仍然可以将从工厂获得的对象配置为常规的Spring bean.

    Note that you still can configure the object obtained from the factory as a regular Spring bean.

    如果您的条件足够简单,则可以避免使用Spring提供的声明性方法来编写自己的代码,例如

    Also if your condition is simple enough, you can avoid writing your own code at all by using declarative approaches provided by Spring, such as Spring Expression language.

    这篇关于如何正确覆盖Spring和Hibernate的BasicDataSource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆