简体   繁体   English

如何在春季使用JPA存储库从服务器检索Blob

[英]How to retrieve blob from server using JPA repository in spring

I've created spring application for CRUD. 我已经为CRUD创建了Spring应用程序。 I can easily write into server data like string,Long,blob but When I try to retrieve it from server. 我可以轻松地写入服务器数据,例如string,Long,blob,但是当我尝试从服务器检索数据时。 I've encountered with difficulty which byte array from server gives in BigInteger from server. 我遇到了来自服务器的字节数组在服务器中提供BigInteger的困难。 How I could get data in byte array instead of BigInteger?When I write in insert byte array this data which column is BLOB. 我如何在字节数组而不是BigInteger中获取数据?当我在插入字节数组中写入此数据时,哪一列是BLOB。 Here is my code 这是我的代码

Repository 知识库

public interface ArriveRepository extends JpaRepository<ArriveEntity,Long>
{ 
    @Query(value = "select arrive.time,air_lines.image,arrive.flight,arrive.destination_uzb," +
            "arrive.destination_eng,arrive.destination_rus,arrive.status,arrive.status_time " +
            "from arrive inner join air_lines on air_lines.id = arrive.airline_id where arrive.arrive_date = (:date1)",nativeQuery = true)
    List<Object[]> getForArriveTerminal(@Param("date1") LocalDate date1);
}

When I retrieve data from server I'm using this class 当我从服务器检索数据时,我正在使用此类

ArriveTerminalDto ArriveTerminalDto

public class ArriveTerminalDto {
   private String time;
   private BigInteger logo;
   private String flight;
   private String destinationUzb;
   private String destinationEng;
   private String destinationRus;
   private String status;
   private String statusTime;
  //getter setter}

Service class 服务等级

  public List<ArriveTerminalDto> getToShow(LocalDate date1)
    {
        List<ArriveTerminalDto> list = new ArrayList<>();
        List<Object[]> list1 = arriveRepository.getForArriveTerminal(date1);
        for(Object[] objects: list1)
        {
            ArriveTerminalDto arriveTerminalDto = new ArriveTerminalDto();
            arriveTerminalDto.setTime((String)objects[0]);
            arriveTerminalDto.setLogo((BigInteger) objects[1]);
            arriveTerminalDto.setFlight((String) objects[2]);
            arriveTerminalDto.setDestinationUzb((String) objects[3]);
            arriveTerminalDto.setDestinationRus((String) objects[4]);
            arriveTerminalDto.setDestinationEng((String) objects[5]);
            arriveTerminalDto.setStatus((String) objects[6]);
            list.add(arriveTerminalDto);
        }
        return list;
    }

This code works but it didn't give me byte array from server. 这段代码有效,但是它没有给我来自服务器的字节数组。 When I try to change BigInteger into byt[] array it gives me following errors from postman 当我尝试将BigInteger更改为byt []数组时,它给我以下来自邮递员的错误

{
    "timestamp": "2019-01-28T09:33:52.038+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "java.math.BigInteger cannot be cast to [B",
    "path": "/arrive/terminal/date=2019-01-27"
}

Changed Object into ArriveTerminalDto but still it give error my following repo 将对象更改为ArriveTerminalDto,但仍然给我以下回购错误

public interface ArriveRepository extends JpaRepository<ArriveEntity,Long>
{

    @Query(value = "select arrive.time,air_lines.image,arrive.flight,arrive.destination_uzb," +
            "arrive.destination_eng,arrive.destination_rus,arrive.status,arrive.status_time " +
            "from arrive inner join air_lines on air_lines.id = arrive.airline_id where arrive.arrive_date = (:date1)",nativeQuery = true)
    List<ArriveTerminalDto> getForArriveTerminal(@Param("date1") LocalDate date1);
}

Try to change entity definition to handle byte[] directly, but suggest JPA to interpret it as Lob. 尝试更改实体定义以直接处理byte [],但建议JPA将其解释为Lob。 You can do it with @Lob annotation: 您可以使用@Lob注释来做到这一点:

public class ArriveTerminalDto {
    private String time;
    @Lob
    private byte[] logo;
    private String flight;
    private String destinationUzb;
    private String destinationEng;
    private String destinationRus;
    private String status;
    private String statusTime;
}

Laster, as @Clijsters suggested, you can change your repo to return List<ArriveTerminalDto> . 最后,如@Clijsters所建议,您可以更改您的存储库以返回List<ArriveTerminalDto>

Why don't you take a look at the Spring Content community project. 您为什么不看一下Spring Content社区项目。 This project allows you to associate content with Spring Data entities. 该项目允许您将内容与Spring Data实体相关联。 Think Spring Data but for Content, or unstructured data. 考虑Spring数据,但考虑内容或非结构化数据。 This can also give you REST endpoints for the content as well, like Spring Data REST. 这也可以为您提供内容的REST端点,例如Spring Data REST。

This approach will give you a clear abstraction for your content with implementations for many different types of storage. 这种方法将为您的内容提供清晰的抽象,其中包含许多不同类型的存储的实现。 It is stream-based, rather than byte-based. 它基于流,而不是基于字节。 Using byte[] won't work if you want to transfer very large files. 如果要传输非常大的文件,则不能使用byte []。 Also getting databases to stream properly is very idiosyncratic. 使数据库正确地流式传输也很特别。 You probably don't want to figure all that out yourself when Spring Content already has. 当Spring Content已经拥有时,您可能不想自己解决所有问题。

This is pretty easy to add to your existing projects. 这很容易添加到您的现有项目中。 I am not sure if you are using Spring Boot, or not. 我不确定您是否正在使用Spring Boot。 I'll give a non-spring boot example: 我将给出一个非春季启动示例:

pom.xml 的pom.xml

   <!-- Java API -->
   <dependency>
      <groupId>com.github.paulcwarren</groupId>
      <artifactId>spring-content-jpa</artifactId>
      <version>0.5.0</version>
   </dependency>
   <!-- REST API (if you want it) -->
   <dependency>
      <groupId>com.github.paulcwarren</groupId>
      <artifactId>spring-content-rest</artifactId>
      <version>0.5.0</version>
   </dependency>

Configuration 组态

@Configuration
@EnableJpaStores
@Import("org.springframework.content.rest.config.RestConfiguration.class")
public class ContentConfig {

    // schema management
    // 
    @Value("/org/springframework/content/jpa/schema-drop-mysql.sql")
    private Resource dropContentTables;

    @Value("/org/springframework/content/jpa/schema-mysql.sql")
    private Resource createContentTables;

    @Bean
    DataSourceInitializer datasourceInitializer() {
        ResourceDatabasePopulator databasePopulator =
                new ResourceDatabasePopulator();

        databasePopulator.addScript(dropContentTables);
        databasePopulator.addScript(createContentTables);
        databasePopulator.setIgnoreFailedDrops(true);

        DataSourceInitializer initializer = new DataSourceInitializer();
        initializer.setDataSource(dataSource());
        initializer.setDatabasePopulator(databasePopulator);

        return initializer;
    }
}

To associate content, add Spring Content annotations to your account entity. 要关联内容,请将Spring Content批注添加到您的帐户实体。

ArriveEntity.java ArriveEntity.java

@Entity
public class ArriveEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    .. existing fields...    


    @ContentId
    private String contentId;

    @ContentLength
    private long contentLength = 0L;

    // if you have rest endpoints
    @MimeType
    private String mimeType = "text/plain";
}

Create a "store": 创建一个“商店”:

ArrivEntityContentStore.java ArrivEntityContentStore.java

@StoreRestResource(path="arriveEntityContent)
public interface ArrivEntityContentStore extends ContentStore<ArriveEntity, String> {
}

This is all you need to create REST endpoints @ /arriveEntityContent . 这就是创建REST端点@ /arriveEntityContent When your application starts, Spring Content will look at your dependencies (seeing Spring Content JPA/REST), look at your ArrivEntityContentStore interface and inject an implementation of that interface for JPA. 当您的应用程序启动时,Spring Content将查看您的依赖项(请ArrivEntityContentStore Spring Content JPA / REST),查看您的ArrivEntityContentStore接口,并为JPA注入该接口的实现。 It will also inject a @Controller that forwards http requests to that implementation. 它还将注入一个@Controller ,将@http请求转发到该实现。 This saves you having to implement any of this yourself which I think is what you are after. 这省去了您必须自己实现的任何事情,我认为这是您的追求。

So... 所以...

To access content with a Java API, auto-wire ArrivEntityContentStore and use it methods. 要使用Java API访问内容,请自动ArrivEntityContentStore并使用它的方法。

Or to access content with a REST API: 或使用REST API访问内容:

curl -X POST /arriveEntityContent/{arriveEntityId}

with a multipart/form-data request will store the image in the database and associate it with the account entity whose id is itemId . 带有multipart / form-data请求的请求会将图像存储在数据库中,并将其与ID为itemId的帐户实体相关联。

curl /arriveEntityContent/{arriveEntityId}

will fetch it again and so on...supports full CRUD. 将再次获取它,依此类推...支持完整的CRUD。

There are a couple of getting started guides here . 有一对夫妇快速入门指南的在这里 The reference guide is here . 参考指南在这里 And there is a tutorial video here . 而且还有视频教程在这里 The coding bit starts about 1/2 way through. 编码位大约从1/2开始。

HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM