gpt4 book ai didi

java - 如何正确覆盖 Spring 和 Hibernate 的 BasicDataSource

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:27:02 27 4
gpt4 key购买 nike

目前我在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 字段。

我尝试覆盖 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()(?),所以我宁愿将条件测试移到别处。

我尝试覆盖 setDriverClassName()setUrl() ,它们也有效,据我所知只被调用一次,但我需要提供一些值在 Spring 配置中以触发这些 setter ,因为它们不会以其他方式调用:

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

这可能看起来令人困惑。

有没有更好的解决方案?

最佳答案

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

你有两个选择:

  • 创建一个包装器(使用组合而不是继承)

    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 ...
    }
  • 创建一个工厂(因为您只需要自定义对象的创建阶段,您不需要控制它的整个生命周期)。

     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。

此外,如果您的条件足够简单,您可以使用 Spring 提供的声明式方法完全避免编写自己的代码,例如 Spring Expression language .

关于java - 如何正确覆盖 Spring 和 Hibernate 的 BasicDataSource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4493743/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com