2017-03-16 63 views
4
的实例

我有以下方法(全JdbcInvoiceRepository下面类)在春季启动项目执行:春季启动:无法推断SQL类型用于java.time.LocalDateTime

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; 
} 

我所提供的转换器中:

├── Invoice.java 
├── InvoiceRepository.java 
└── persistance 
    ├── converters 
    │   ├── LocalDateAttributeConverter.java 
    │   └── LocalDateTimeAttributeConverter.java 
    └── JdbcInvoiceRepository.java 

转换为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()); 
    } 
} 

然而,当我在测试执行它,我不断收到错误:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [INSERT INTO invoices VALUES (?, ?, ?, ?, ?)]; nested exception is org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.time.LocalDateTime. Use setObject() with an explicit Types value to specify the type to use.

at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:99) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:662) at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:950) at org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils.executeBatchUpdateWithNamedParameters(NamedParameterBatchUpdateUtils.java:40) at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParameterJdbcTemplate.java:335) at qbs.domain.model.persistance.JdbcInvoiceRepository.bulkSaveInvoices(JdbcInvoiceRepository.java:40) at qbs.domain.model.persistance.JdbcInvoiceRepository$$FastClassBySpringCGLIB$$3c96bc2e.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) at qbs.domain.model.persistance.JdbcInvoiceRepository$$EnhancerBySpringCGLIB$$20bcffdd.bulkSaveInvoices() at qbs.QbsApplicationTests.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) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) at 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) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237) at com.intellij.rt.execution.junit.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) Caused by: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.time.LocalDateTime. Use setObject() with an explicit Types value to specify the type to use. at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1051) at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:454) at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:238) at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:169) at org.springframework.jdbc.core.BatchUpdateUtils.setStatementParameters(BatchUpdateUtils.java:65) at org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils.access$000(NamedParameterBatchUpdateUtils.java:32) at org.springframework.jdbc.core.namedparam.NamedParameterBatchUpdateUtils$1.setValues(NamedParameterBatchUpdateUtils.java:48) at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:960) at org.springframework.jdbc.core.JdbcTemplate$4.doInPreparedStatement(JdbcTemplate.java:950) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633) ... 47 more

什么可以的问题,以及如何解决这一问题?

人数: 的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> 

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); 

    } 

} 

编辑 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() { 
    } 

} 

发票表定义:

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 
); 
+0

请出示发票类 – Jens

+0

@Jens加在编辑 – mCs

+2

所以,你使用的是'JdbcTemplate',你期望从JPA库的东西来帮助你有....虽然这两种持久化技术(和非常低的水平他们有一个链接),他们不像你期望的一样工作。 –

回答

1

1)不要使用JDBC尝试和批量保存JPA实体

2)使用Spring数据JPA代替

3)定义春数据仓库作为这样:

public interface InvoiceRepository extends JpaRepository<Invoice, Long> {} 

4)调用存储库中的save(Iterable iterable方法,并让JPA为您处理所有ORM任务。

例如invoiceRepository.save(invoices)

+1

我想使用'JDBCTemplate',因为这个代码是用于大约500M记录的数据生成器,我相信这样使用低级'JDBCtemplate'可能会更有效率 – mCs