mCs*_*mCs 6 spring spring-jdbc jdbctemplate spring-boot
我JdbcInvoiceRepository在Spring Boot项目中执行了以下方法(下面的完整类):
public int[] bulkSaveInvoices(List<Invoice> invoices){
String insertSQL = "INSERT INTO invoices VALUES (:id, :exactIssueTime, :finalIssueTime, :issuer, :groupID)";
SqlParameterSource[] sqlParams = SqlParameterSourceUtils.createBatch(invoices.toArray());
int[] insertCounts = namedParameterJdbcTemplate.batchUpdate(insertSQL, sqlParams);
return insertCounts;
}
Run Code Online (Sandbox Code Playgroud)
我提供了转换器:
??? Invoice.java
??? InvoiceRepository.java
??? persistance
??? converters
? ??? LocalDateAttributeConverter.java
? ??? LocalDateTimeAttributeConverter.java
??? JdbcInvoiceRepository.java
Run Code Online (Sandbox Code Playgroud)
转换器LocalDateTime:
@Converter(autoApply = true)
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime locDateTime) {
return (locDateTime == null ? null : Timestamp.valueOf(locDateTime));
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我在测试中执行它时,我不断收到错误:
org.springframework.jdbc.BadSqlGrammarException:PreparedStatementCallback; 错误的SQL语法[INSERT INTO发票VALUES(?,?,?,?,?)]; 嵌套异常是org.postgresql.util.PSQLException:无法推断用于java.time.LocalDateTime实例的SQL类型.使用带有显式Types值的setObject()来指定要使用的类型.
org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:99)org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate (AbstractFallbackSQLExceptionTranslator.java:81)org.springframework上的org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649).位于org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:950)的jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:662)位于org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils.executeBatchUpdateWithNamedParameters(NamedParameterBatchUpdateUtils. java:40)at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParame)terjdbcTemplate.java:335)在qbs.domain.model.persistance.JdbcInvoiceRepository.bulkSaveInvoices(JdbcInvoiceRepository.java:40)的qbs.domain.model.persistance.JdbcInvoiceRepository $$ FastClassBySpringCGLIB $$ 3c96bc2e.invoke()at org.springframework. cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)atg.springframework.aop.framework.CglibAopProxy $ CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.的java:157)在org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)在org.springframework.aop.framework .cglibAopProxy $ DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)位于qbs.QbsApp的qbs.domain.model.persistance.JdbcInvoiceRepository $$ EnhancerBySpringCGLIB $$ 20bcffdd.bulkSaveInvoices()licationTests.fillDB(QbsApplicationTests.java:33)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 43)在org.junit.internal.runners.model的org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50)的java.lang.reflect.Method.invoke(Method.java:498)中. ReflectiveCallable.run(ReflectiveCallable.java:12)在org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)在org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)在Org.springframework的org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) .test.context.junit4.statements.SpringRepea t.evaluate(SpringRepeat.java:84)在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)在org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)在组织.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)在org.junit.runners.ParentRunner $ 1.schedule(ParentRunner .java:71)org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)org.junit.runners.ParentRunner $ 2.评估(ParentRunner.java:268)org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks. java:70)在org.springframework.test.contex的org.junit.runners.ParentRunner.run(ParentRunner.java:363)t.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)at com .intellij.rt.execution.junit.IdeaTestRunner $ Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)在com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)在com.intellij.rt.execution .unit.JUnitStarter.main(JUnitStarter.java:70)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl .java:43)at java.lang.reflect.Method.invoke(Method.java:498)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)引起:org.postgresql. util.PSQLException:无法推断用于java.time.LocalDateTime实例的SQL类型.使用带有显式Types值的setObject()来指定要使用的类型.org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1051)org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:454)at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils)的.java:238)在org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:169)在org.springframework.jdbc.core.BatchUpdateUtils.setStatementParameters(BatchUpdateUtils.java:65)在org.springframework.jdbc. org.springframework.jdbc.core.JdbcTemplate $ 4.doInPreparedStatement中的org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils $ 1.setValues(NamedParameterBatchUpdateUtils.java:48)中的core.namedparam.NamedParameterBatchUpdateUtils.access $ 000(NamedParameterBatchUpdateUtils.java:32) (jdbcTemplate.java:960)org.springframework.jdbc.core.JdbcTemplate $ 4.doInPreparedStatement(JdbcTemplate.java:950)org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTempla)te.java:633)......还有47个
可能是什么问题以及如何解决这个问题?
清单:pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--For less boilerplate code-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--JSR 330 for DI in Java - @Inject-->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
Run Code Online (Sandbox Code Playgroud)
JdbcInvoiceRepository
@Repository
public class JdbcInvoiceRepository {
@Inject
private JdbcTemplate jdbcTemplate;
@Inject
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private SimpleJdbcInsert simpleJdbcInsert;
@PostConstruct
public void setupSimpleJdbcInsert(){
simpleJdbcInsert =
new SimpleJdbcInsert(jdbcTemplate).withTableName("invoices").usingGeneratedKeyColumns("id");
}
public int[] bulkSaveInvoices(List<Invoice> invoices){
String insertSQL = "INSERT INTO invoices VALUES (:id, :exactIssueTime, :finalIssueTime, :issuer, :groupID)";
SqlParameterSource[] sqlParams = SqlParameterSourceUtils.createBatch(invoices.toArray());
int[] insertCounts = namedParameterJdbcTemplate.batchUpdate(insertSQL, sqlParams);
return insertCounts;
}
public Long getInvoiceCount() {
return jdbcTemplate.queryForObject("select count(*) from invoices",
Long.class);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑Invoice.java
@Data
@AllArgsConstructor
@Entity
@Table(name = "invoices")
public class Invoice {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
@Column(name = "exact_iss_time")
private LocalDateTime exactIssueTime;
@Column(name = "final_iss_time")
private LocalDateTime finalIssueTime;
@Column(name = "issuer")
private String issuer;
@Column(name = "groupid")
private Integer groupID;
protected Invoice() {
}
}
Run Code Online (Sandbox Code Playgroud)
发票表定义:
CREATE TABLE invoices (
id SERIAL PRIMARY KEY,
exact_iss_time TIMESTAMP NOT NULL,
actual_iss_time TIMESTAMP NOT NULL,
issuer TEXT NOT NULL,
groupid INTEGER NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
Pau*_*NUK -2
1) 不要使用 JDBC 尝试批量保存 JPA 实体
2)使用Spring Data JPA代替
3)定义一个Spring数据存储库,如下所示:
public interface InvoiceRepository extends JpaRepository<Invoice, Long> {}
Run Code Online (Sandbox Code Playgroud)
4) 在您的存储库上调用 save(Iterable 可迭代方法),让 JPA 为您处理所有 ORM 任务。
例如invoiceRepository.save(invoices)
| 归档时间: |
|
| 查看次数: |
5516 次 |
| 最近记录: |