更新:显然Tomcat,从7.0.11开始,为您关闭DataSource,因此它在webapp的contextDestroyed中不可用.请参阅:https://issues.apache.org/bugzilla/show_bug.cgi?id = 25060
嗨,
我正在使用Spring 3.0和Java 1.6.
如果我以这种方式获得数据源:
<bean id="dataSource" class="my.data.Source" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:home"/>
<property name="username" value="user"/>
<property name="password" value="pw"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
然后在bean被销毁时关闭数据源.
如果我得到这样的数据源:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/db" />
Run Code Online (Sandbox Code Playgroud)
那么我是否必须在contextDestroyed监听器中显式关闭数据源?
谢谢,
保罗
首先,我不能使用声明性@Transactional方法,因为应用程序有多个 JDBC 数据源,我不想厌倦细节,但只要说 DAO 方法传递了正确的数据源来执行逻辑就足够了。所有 JDBC 数据源都具有相同的架构,当我为 ERP 系统公开其余服务时,它们是分开的。
由于这个遗留系统,有很多我无法控制的长期锁定记录,所以我想要脏读。
使用 JDBC 我将执行以下操作:
private Customer getCustomer(DataSource ds, String id) {
Customer c = null;
PreparedStatement stmt = null;
Connection con = null;
try {
con = ds.getConnection();
con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
stmt = con.prepareStatement(SELECT_CUSTOMER);
stmt.setString(1, id);
ResultSet res = stmt.executeQuery();
c = buildCustomer(res);
} catch (SQLException ex) {
// log errors
} finally {
// Close resources
}
return c;
}
Run Code Online (Sandbox Code Playgroud)
好吧,我知道有很多样板。JdbcTemplate所以自从我使用spring以来我就尝试过。
使用Jdbc模板
private Customer getCustomer(JdbcTemplate t, String id) …Run Code Online (Sandbox Code Playgroud) 假设我有一个具有两个不同的一对多关系的对象.很像:
Customer 1<->M Brands 和 Customer 1<->M Orders
让我们说我的对象Customer有两个与这两个对象相关的列表.
我读过这个例子:http:
//forum.springsource.org/showthread.php?50616-rowmapper
-with-one-to-many- query,它解释了如何用一对一的关系来做到这一点.为了您的方便,这里是ResultSetExtractor覆盖:
private class MyObjectExtractor implements ResultSetExtractor{
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
Map<Integer, MyObject> map = new HashMap<Integer, MyObject>();
MyObject myObject = null;
while (rs.next()) {
Integer id = rs.getInt("ID);
myObject = map.get(id);
if(myObject == null){
String description = rs,getString("Description");
myObject = new MyObject(id, description);
map.put(id, myObject);
}
MyFoo foo = new MyFoo(rs.getString("Foo"), rs.getString("Bar"));
myObject.add(myFoo);
}
return new ArrayList<MyObject>(map.values());; …Run Code Online (Sandbox Code Playgroud) 我有一个看起来像这样的课程.我需要从两个数据库表中填充它,如下所示.有没有首选的方法呢?
我的想法是让服务类选择List<>通过ResultSetExtractor从DAO.然后foreach在该列表上执行操作,并List<>通过另一个人为个人选择一封电子邮件ResultSetExtractor,并将其附加到foreach循环中.
有没有更好的方法,还是这样的好?
public class Person {
private String personId;
private String Name;
private ArrayList<String> emails;
}
create table Person (
person_id varchar2(10),
name varchar2(30)
);
create table email (
person_id varchar2(10),
email varchar2(30)
);
Run Code Online (Sandbox Code Playgroud) 我知道这可能是重复的,具有讽刺意味的是,在我开始阅读这里和那里之前,我知道我知道它是什么(无需说出来但我仍然会说,请纠正我错在哪里):
它减轻程序员必须使用transaction.begin()和transaction.begin().如果你有一个调用两个DAO方法的方法,通常每个方法都包含commit()并transaction.begin 包含实际操作并调用它们,那么它将导致两个事务(如果前面的dao方法也应该回滚,则可能存在回滚问题).但是,如果你用transaction.commit你的方法,然后这些人DAO呼叫将被包裹在一个单一的@transactional- begin()周期.当然,如果你使用commit() DAO,一定不要使用@Transactional和begin() 方法我认为.
我正在创建一个使用嵌入式hsqldb的基于Spring的Web应用程序.我的spring配置非常简单:
<jdbc:embedded-database id="dataSource" type="HSQL" >
<jdbc:script location="classpath:scripts/create-table-if-not-exists" />
</jdbc:embedded-database>
Run Code Online (Sandbox Code Playgroud)
但是使用此配置,所有数据都存储在内存中.这是创建的数据源URL
jdbc:hsqldb:mem:dataSource
Run Code Online (Sandbox Code Playgroud)
我需要将数据保存到文件中.这样我可以在服务器重启后再次使用它.
我有一个简单的模型,我希望使用Spring JDBCTemplate在MySQL中保存这些实例.我使用DAO,使用简单的sql(insert into user(id, email...) value (:id, :email...))保存模型对象.是否有任何框架可以从模型中提取参数(当模型只是具有公共字段的POJO时).所以,我需要类似于Spring的东西BeanPropertySqlParameterSource,但是能够使用公共字段而不是属性.
模型类的示例:
public class User {
public int id;
public String email;
public String login;
public String password;
}
Run Code Online (Sandbox Code Playgroud)
我知道扩展AbstractSqlParameterSource可以解决我的问题,但我希望找到现有的框架.
UPD
实施基于AbstractSqlParameterSource:
public class PublicFieldsSqlParameterSource extends AbstractSqlParameterSource {
Map<String, Object> props = new HashMap<>();
public PublicFieldsSqlParameterSource(Object object) {
Field[] fields = object.getClass().getFields();
for (Field field : fields) {
String name = field.getName();
try {
Object value = field.get(object);
props.put(name, value);
} catch (IllegalAccessException ignored) { …Run Code Online (Sandbox Code Playgroud) OracleTypes.ARRAY多次调用带有输入参数的Oracle存储过程时,会出现以下错误: -
org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call EMP_SCHEMA.GET_EMPLOYEE_LIST(?, ?)}]; SQL state [72000]; error code [1000]; ORA-01000: maximum open cursors exceeded; nested exception is java.sql.SQLException: ORA-01000: maximum open cursors exceeded
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
Run Code Online (Sandbox Code Playgroud)
JDBC模板配置是: -
<bean id="commonsDbcpNativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg>
<ref bean="dataSource" />
</constructor-arg>
<property name="nativeJdbcExtractor" ref="commonsDbcpNativeJdbcExtractor" />
</bean>
Run Code Online (Sandbox Code Playgroud)
存储过程类: -
public class GetEmployees extends StoredProcedure {
public GetEmployees(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate, "EMP_SCHEMA.GET_EMPLOYEE_LIST");
declareParameter(new SqlParameter("p_emp_id_list", OracleTypes.ARRAY, "TBL_EMP_ID"));
declareParameter(new SqlOutParameter(CURSOR, OracleTypes.CURSOR, new EmployeeDataRowMapper())); …Run Code Online (Sandbox Code Playgroud) 我有这样的查询,我试图通过比较元组来过滤结果集(如IN子句中的SQL多列):
select *
from mytable
where (key, value) in (values
('key1', 'value1'),
('key2', 'value2'),
...
);
Run Code Online (Sandbox Code Playgroud)
这是有效的语法,并在我的Postgres 9.3数据库上正常工作.
我想通过Spring JDBC调用此查询,其中in值对来自a List<Map<String,String>>.
做这样的事情会很好:
List<Map<String, String>> valuesMap = ...;
String sql = "select * from mytable where (key, value) in (values :valuesMap)";
SqlParameterSource params = new MapSqlParameterSource("valuesMap", valuesMap);
jdbcTemplate.query(sql, params, rowMapper);
Run Code Online (Sandbox Code Playgroud)
当我尝试这个时,我得到:
org.postgresql.util.PSQLException: No hstore extension installed.
at org.postgresql.jdbc2.AbstractJdbc2Statement.setMap(AbstractJdbc2Statement.java:1707) ~[postgresql-9.3-1101-jdbc41.jar:na]
at org.postgresql.jdbc2.AbstractJdbc2Statement.setObject(AbstractJdbc2Statement.java:1910) ~[postgresql-9.3-1101-jdbc41.jar:na]
at org.postgresql.jdbc3g.AbstractJdbc3gStatement.setObject(AbstractJdbc3gStatement.java:36) ~[postgresql-9.3-1101-jdbc41.jar:na]
at org.postgresql.jdbc4.AbstractJdbc4Statement.setObject(AbstractJdbc4Statement.java:47) ~[postgresql-9.3-1101-jdbc41.jar:na]
at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:427) ~[spring-jdbc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:235) ~[spring-jdbc-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:150) …Run Code Online (Sandbox Code Playgroud) 我有一个Spring data存储库:
@Repository
interface SomeRepository extends CrudRepository<Entity, Long> {
Stream<Entity> streamBySmth(String userId);
}
Run Code Online (Sandbox Code Playgroud)
我在一些Spring bean中调用该方法:
@Scheduled(fixedRate = 10000)
private void someMethod(){
someRepository.streamBySmth("smth").forEach(this::callSomeMethod);
}
Run Code Online (Sandbox Code Playgroud)
我正在使用MySQL数据库.当我在一些成功的方法调用后运行应用程序时,它会引发异常:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08001
o.h.engine.jdbc.spi.SqlExceptionHelper : Could not create connection to database server.
o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
org.springframework.dao.DataAccessResourceFailureException: Unable to acquire JDBC Connection; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Run Code Online (Sandbox Code Playgroud)
看来,Spring没有正确关闭连接.如果我已经将方法返回值更改为List从Stream它正常工作.
更新: Spring Boot版本是1.4.1.RELEASE
spring-jdbc ×10
java ×8
spring ×5
jdbc ×2
jdbctemplate ×2
datasource ×1
hsqldb ×1
java-stream ×1
jndi ×1
oracle ×1
postgresql ×1
spring-data ×1
tomcat7 ×1
transactions ×1