我有一个Spring应用程序,当前使用存储过程执行一些查询。配置是这样的:
数据源:
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.ReplicationDriver"/>
<property name="url" value="jdbc:mysql:replication://master,slave1,slave2/db?allowMultiQueries=true"/>
<property name="username" value="${db.dbusername}"/>
<property name="password" value="${db.dbpassword}"/>
<property name="defaultReadOnly" value="true"/>
</bean>
<bean id="jdbcDeviceDAO" class="dao.jdbc.JdbcDeviceDAO">
<property name="dataSource" ref="dataSource"/>
</bean>
DAO:
public class JdbcDeviceDAO implements DeviceDAO {
// ...
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.procGetCombinedDeviceRouting = new SimpleJdbcCall(jdbcTemplate)
.withProcedureName("get_combined_device_routing");
// ...
}
public CombinedDeviceRouting getCombinedDeviceRouting(String deviceName, String deviceNameType) {
SqlParameterSource in = createParameters(deviceName, deviceNameType);
Map<String, Object> results = this.procGetCombinedDeviceRouting.execute(in);
return extractResults(results);
}
现在,当我调用getCombinedDeviceRouting(...)时,它失败并出现以下异常:
org.springframework.dao.TransientDataAccessResourceException: CallableStatementCallback; SQL [{call get_combined_device_routing()}]; Connection is read-only. Queries leading to data modification are not allowed; nested exception is java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
我知道连接是只读的,我需要它是这样的,所以查询在从属主机之间进行负载平衡。但是存储过程实际上是只读的,它只是很多SELECT语句,实际上我尝试将READS SQL DATA添加到它的定义中,但它没有用。
最后我开始阅读mysql的连接器代码了,我发现了这个:
protected boolean checkReadOnlySafeStatement() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return this.firstCharOfStmt == 'S' || !this.connection.isReadOnly();
}
}
这听起来很幼稚,但连接器检查我的语句是否为只读,只需将第一个字符与&#39; S&#39; 如果是这种情况,似乎无法在从属主机上调用存储过程,因为该语句以&#39; C&#39; (打电话......)。
有谁知道这个问题是否有解决方法?或者假设第一次角色检查我错了吗?
答案 0 :(得分:1)
似乎this is a bug with the driver我看了一下代码,看看是否有一个简单的扩展点,但看起来你必须扩展很多类来影响这种行为:(< / p>