首页 > 解决方案 > 是否可以将 BYTEA 字段与 Spring Data JDBC(不是 JPA)一起使用

问题描述

我正在尝试使用 Spring Data JDBC 读取具有 BYTEA 字段的 Postgresql 表中的一行,但它因Couldn't find PersistentEntity for type byte!MappingException 而失败。该方法失败org.springframework.data.jdbc.core.EntityRowMapper.populateProperties,它被解释byte[]isCollectionLike并且(我想)试图创建 SQL 以将其读取为 PostgreSQL 字节数组,而不是它的 blob。

有很多关于如何使用 JPA 或手动 JdbcTemplate 执行此操作的示例,但 Spring Data JDBC 的文档不那么丰富。我无法想象我是第一个遇到这个问题的人。

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:782) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:763) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at markscottwright.Application.main(Application.java:18) ~[classes/:na]
Caused by: org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type byte!
    at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:79) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.data.jdbc.core.SqlGeneratorSource.lambda$getSqlGenerator$0(SqlGeneratorSource.java:41) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) ~[na:na]
    at org.springframework.data.jdbc.core.SqlGeneratorSource.getSqlGenerator(SqlGeneratorSource.java:40) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.data.jdbc.core.DefaultDataAccessStrategy.sql(DefaultDataAccessStrategy.java:360) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.data.jdbc.core.DefaultDataAccessStrategy.findAllByProperty(DefaultDataAccessStrategy.java:252) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.data.jdbc.core.EntityRowMapper.populateProperties(EntityRowMapper.java:94) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.data.jdbc.core.EntityRowMapper.mapRow(EntityRowMapper.java:74) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:678) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:616) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:693) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:747) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:215) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:227) ~[spring-jdbc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.data.jdbc.core.DefaultDataAccessStrategy.findAll(DefaultDataAccessStrategy.java:217) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.data.jdbc.core.JdbcAggregateTemplate.findAll(JdbcAggregateTemplate.java:171) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at org.springframework.data.jdbc.repository.support.SimpleJdbcRepository.findAll(SimpleJdbcRepository.java:84) ~[spring-data-jdbc-1.0.9.RELEASE.jar:1.0.9.RELEASE]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295) ~[spring-tx-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.1.9.RELEASE.jar:2.1.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at com.sun.proxy.$Proxy44.findAll(Unknown Source) ~[na:na]
    at markscottwright.Application.run(Application.java:23) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    ... 5 common frames omitted

2019-08-20 13:36:00.335  INFO 10604 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2019-08-20 13:36:00.344  INFO 10604 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

我的桌子:

CREATE TABLE IF NOT EXISTS test_entity (
    id                              INTEGER PRIMARY KEY,
    byte_array                      BYTEA
    );

insert into test_entity values (1, decode('00010203', 'hex'));

测试实体.java

package markscottwright;

import org.springframework.data.annotation.Id;

public class TestEntity {
    @Id
    public Long id;
    public byte[] byteArray;
}

TestEntityRepository.java

package markscottwright;

import org.springframework.data.repository.CrudRepository;

public interface TestEntityRepository extends CrudRepository<TestEntity, Long> {
}

我的应用程序.java

package markscottwright;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;

@EnableJdbcRepositories
@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    TestEntityRepository testEntities;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        testEntities.findAll().forEach(System.out::println);
    }

}

我的 pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>markscottwright</groupId>
  <artifactId>springdata-bytea</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
  </parent>

  <properties>
    <java.version>11</java.version>
  </properties>


  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

标签: springspring-data-jdbc

解决方案


这是作为DATAJDBC-327DATAJDBC-259的一部分实现的,它们在 1.1.x 版本中可用。

最新版本是里程碑存储库https://repo.spring.io/milestone提供的 1.1.0.RC2


推荐阅读