Spring JDBC VS JDBC之间的主要区别是什么?
我需要一次性在数据库中插入数千条记录.我在我的应用程序中使用spring JDBC模板.
下面是我到目前为止编写的代码,它一次执行所有插入.所以,如果我有10,000个用户,他们一次插入.但我想要的是批量执行它们,例如一批500条记录,等等.
@Override
public void saveBatch(final List<Employee> employeeList) {
final int batchSize = 500;
getJdbcTemplate().batchUpdate(QUERY_SAVE,
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
Employee employee = employeeList.get(i);
ps.setString(1, employee.getFirstname());
ps.setString(2, employee.getLastname());
ps.setString(3, employee.getEmployeeIdOnSourceSystem());
}
@Override
public int getBatchSize() {
return employeeList.size();
}
});
}
Run Code Online (Sandbox Code Playgroud)
如何更改上面的代码,以便代替employeeList.size()作为批量大小,我们可以将批量大小称为500,执行它们然后下一个500,依此类推?
请帮忙.
在Spring中,当我们插入数据库时,我们可以使用JdbcDaoSupport或不使用.我的问题是,使用它有什么好处,在哪种情况下我们应该使用它?
我目前正在学习更多关于在Spring Boot webapp中实现JDBC和使用数据库的知识,我在帖子的底部遇到了以下Stack Trace.
我创建了一个简单的Employee模型,我试图在我的main()所在的同一个类上执行一些数据库代码.模型和主类是整个项目中存在的唯一两个java文件.我正在尝试实现以下run()代码,该代码覆盖了接口CommandLineRunner中的那个,但是我没有得到log.info之后的日志("A部分:"):
log.info("Part A:")
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
Run Code Online (Sandbox Code Playgroud)
- 我注意到了:
我注意到堆栈跟踪开始之前的日志的最后一行来自:"Thread-1"而不是"main".我认为这意味着来自除main之外的某个地方的线程在正常关闭之前遇到错误和关闭连接.
另外,我认为因为HikariPool在"peer's close_notify"之前关闭,我认为它指的是HikariPool的正常关闭,我无法看到我一直试图获取的最后一点日志记录.我希望看到的最后一点日志记录是已插入到我的数据库中的员工的日志记录.
我希望看到的最后一点日志记录应该从这行代码中获得:
employees.forEach(employee -> {log.info(employee.toString());
log.info("part a");});
Run Code Online (Sandbox Code Playgroud)
- 要注意的事项:
由于日志中的这一行,我以为我会看到员工插入到我的数据库中,但当我直接在MySQL命令行客户端上查询时,它返回一个空集:
2018-11-03 21:08:35.362 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : rows affected: 1
Run Code Online (Sandbox Code Playgroud)
我不明白为什么在没有任何内容插入数据库时,行会受到影响.
堆栈跟踪和日志:(下面粘贴的堆栈跟踪实际上会重复几次,但我为了简洁而将其剪掉了.)
2018-11-03 21:08:32.997 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : Starting JdbcTest1Application on KitKat with PID 2408 (C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1\target\classes started by Nano in C:\Users\Nano\Downloads\jdbc-test1\jdbc-test1)
2018-11-03 21:08:33.003 INFO 2408 --- [ main] c.j.jdbctest1.JdbcTest1Application : No …Run Code Online (Sandbox Code Playgroud) 所以我知道一些相对的差异,即ResultSet与数据库有"开放连接",而RowSet以"断开连接"的方式工作.
但这几乎是我理解的(可能是不正确的:)
那么我的问题是 - 在什么情况下比另一种更可取?他们各自的优势/劣势是什么?
从我的感觉是RowSet,在断开模式下工作,特别是对于"只读"查询,在高度并发的系统中会有更好的性能.那是对的吗?如果是这样的话,可以说RowSet总是比ResultSet更适合只读查询吗?
如果我正确迭代RowSet不会抛出SQL异常,但这是一个好处吗?另一个是RowSet是可序列化的.但我担心的主要是从绩效角度来看会有什么选择呢?
有任何想法吗?我的知识中有一些缺失,显而易见:)
我问的原因是我想在实现Spring-Jdbc的ResultSetExtractor接口与在处理一些数据时返回SqlRowSet之间做出选择.这个问题让我很好奇如何决定什么时候选择,除了扔硬币:)
在数据库连接闲置一段时间后,我的应用程序中出现以下异常:
... An I/O error occured while sending to the backend.; nested exception is org.postgresql.util.PSQLException: An I/O error occured while sending to the backend.] with root cause
java.net.SocketException: Operation timed out
at java.net.SocketInputStream.socketRead0(Native Method)
Run Code Online (Sandbox Code Playgroud)
在psql中发生同样的问题我没有连接到本地数据库的问题,所以我很确定问题出在RDS上.
psql=> select 'ok';
SSL SYSCALL error: Operation timed out
psql=> select 'ok';
SSL SYSCALL error: EOF detected
The connection to the server was lost. Attempting reset: Succeeded.
Run Code Online (Sandbox Code Playgroud)
我发现了另一个问题,这个问题表明可以改善这种情况的工作(超时现在需要更长时间),但没有解决它.
我正在使用Spring Boot with JDBC(tomcat连接池)和JDBCTemplate.
有解决方法还是修复?也许强制连接池测试和重新连接?我如何在这种环境下做到这一点?
编辑:这是我的连接字符串
jdbc:postgresql://myhost.c2estvxozjm3.eu-west-1.rds.amazonaws.com/dashboard?tcpKeepAlive=true
Run Code Online (Sandbox Code Playgroud)
解:
根据所选答案中的建议编辑RDS服务器端TCP_KeepAlive参数.我正在使用的参数是:
tcp_keepalives_count 5
tcp_keepalives_idle 200 …Run Code Online (Sandbox Code Playgroud) 我正在使用Spring的JdbcTemplate和StoredProcedure类.我无法让存储过程类为我工作.
我在oracle数据库上有一个存储过程.它的签名是
CREATE OR REPLACE PROCEDURE PRC_GET_USERS_BY_SECTION
(user_cursor OUT Pkg_Types.cursor_type
, section_option_in IN Varchar2
, section_in IN Varchar2) AS ....
Run Code Online (Sandbox Code Playgroud)
哪里
TYPE cursor_type IS REF CURSOR;
Run Code Online (Sandbox Code Playgroud)
我创建了以下存储过程类来从oracle过程中获取信息
private class MyStoredProcedure extends StoredProcedure
{
public MyStoredProcedure(JdbcTemplate argJdbcTemplate)
{
super(argJdbcTemplate, "PRC_GET_USERS_BY_SECTION");
declareParameter(new SqlOutParameter("output", OracleTypes.CURSOR));
declareParameter(new SqlParameter("input1", Types.VARCHAR));
declareParameter(new SqlParameter("input2", Types.VARCHAR));
compile();
}
public Map<String, Object> execute() {
Map<String, Object> inParams = new HashMap<String, Object>();
inParams.put("input1", "BG");
inParams.put("input2", "FE");
Map output = execute(inParams);
return output;
}
}
Run Code Online (Sandbox Code Playgroud)
我在我的一个DAO类中的方法中调用它
public List<String> getUserListFromProcedure() throws BatchManagerException …Run Code Online (Sandbox Code Playgroud) 我正在研究如何在Spring Framework中使用JDBC对数据库执行查询.
我正在学习本教程:http://www.tutorialspoint.com/spring/spring_jdbc_example.htm
在本教程中,我定义了一个StudentDAO接口,它只定义了我想要的CRUD方法.
然后定义Student类,它是我想要在Student数据库表上保留的实体.
然后定义StudentMapper类,它是RowMapper接口的特定实现,在这种情况下,用于将ResultSet中的特定记录(由查询返回)映射到Student对象.
然后,我有StudentJDBCTemplate是rappresent我实施StudentDAO界面,在这个类我实现的接口中定义的CRUD方法.
好了,现在我有一个关于如何疑问StudentMapper类的工作:在这个StudentJDBCTemplate类有定义的返回是在学生数据库表中的所有记录的列表的方法,这其中:
public List<Student> listStudents() {
String SQL = "select * from Student";
List <Student> students = jdbcTemplateObject.query(SQL,
new StudentMapper());
return students;
}
Run Code Online (Sandbox Code Playgroud)
你怎么看,这个方法返回一个List of Student对象并按以下方式工作:
它首先要做的是定义返回 SQL String中Student数据库表中所有记录的查询.
然后通过jdbcTemplateObject对象上的查询方法调用执行此查询(这是JdbcTemplate Spring类的一个等级**
此方法有两个参数:SQL String(包含必须执行的SQL查询)和一个新的StudentMapper对象,它接受查询返回的ResultSet对象并将其记录映射到新的Student对象上
在这里阅读:http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html sayas:执行给定静态SQL的查询,将每一行映射到Java通过RowMapper对象.
我的疑问是有关事实,我的StudentMapper映射使用一个Student对象上一个ResultSet记录 …
我想知道是否有人可以帮助我.我尝试使用Spring JDBC编写代码时遇到了一个问题.当我运行服务器时,我收到了标题中提到的消息.我有谷歌它,有人说你应该导入ojdbc.jar.但是,我已经导入了它.这是我的代码:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@192.168.0.13:1521/orcl" />
<property name="username" value="Hibernate" />
<property name="password" value="123456" />
</bean>
</beans>
Run Code Online (Sandbox Code Playgroud)
如果我做错了,请提出建议.提前谢谢了.
我正在使用Spring JDBC,我对如何处理多个一对多关系(或多对多关系)有点不确定.在这种情况下,我将一个存储库注入我的resultsetextractors之一,以便我可以检索其关联.这是这样做的吗?这不好吗?还有其他更好的方法吗?
注意:我遗漏了注册库
public class SomeResultSetExtractor implements ResultSetExtractor {
public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
List result = new LinkedList();
while (rs.next()) {
SomeObject object = new SomeObject(rs.getString(1), rs.getLong(2));
result.add(object);
List<AnotherObject> otherObjects = anotherRepository.findAllById(object.getId);
object.setOtherObjects(otherObjects);
// and so on
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
Okey所以在阅读Dmytro Polivenok之后回答我改为RowMapper界面,而我目前正在使用其他存储库来填充我在我的示例中显示的所有关联.这是一个很好的方式吗?
spring-jdbc ×10
spring ×6
java ×5
jdbc ×5
oracle ×2
spring-boot ×2
amazon-rds ×1
jdbctemplate ×1
mysql ×1
postgresql ×1
rowset ×1
spring-mvc ×1
springsource ×1
sslexception ×1