Spring-data-jpa存储blob

时间:2015-07-17 05:49:15

标签: blob spring-data-jpa

什么是最好的"或使用spring-data-jpa存储blob实体的规范方法?

dx

6 个答案:

答案 0 :(得分:7)

TL; DR

您可以看到sample project on my github。该项目显示了如何将数据流入/流出数据库。

问题

关于将@Lob映射为byte[]失败(IMO)blob的主要优势 - 流媒体的所有建议。使用byte[],所有内容都会被加载到内存中。可能没问题,但是如果你选择 L arge O 这个项目你可能想要流式传输。

解决方案

映射

@Entity
public class MyEntity {

    @Lob
    private Blob data;

    ...

}

配置

公开hibernate SessionFactory CurrentSession ,这样你就可以掌握LobCreator。在 application.properties

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

将会话工厂公开为bean:

@Bean // Need to expose SessionFactory to be able to work with BLOBs
public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
    return hemf.getSessionFactory();
}

创建blob

@Service
public class LobHelper {

    private final SessionFactory sessionFactory;

    @Autowired
    public LobHelper(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Blob createBlob(InputStream content, long size) {
        return sessionFactory.getCurrentSession().getLobHelper().createBlob(content, size);
    }

    public Clob createClob(InputStream content, long size, Charset charset) {
        return sessionFactory.getCurrentSession().getLobHelper().createClob(new InputStreamReader(content, charset), size);
    }
}

另外 - 正如评论中所指出的那样 - 只要您使用包含流的@Blob,您就需要在交易中。只需标记工作部分@Transactional即可。

答案 1 :(得分:1)

自动装配存储库界面并调用传递实体对象的save方法。

我有类似的设置,效果很好:

@Autowired
Repository repository;

repository.save(entity);

@Entity
@Table(name = "something")
public class Message {

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

    @Lob
    @Column
    private byte[] data;

答案 2 :(得分:1)

Spring Data不处理BLOB但Spring Content处理BLOB。具体而言,Spring Content JPA将内容作为BLOB存储在数据库中,并通过注释将该内容与实体相关联。

  

的pom.xml

   <!-- Java API -->
   <dependency>
      <groupId>com.github.paulcwarren</groupId>
      <artifactId>spring-content-jpa-boot-starter</artifactId>
      <version>0.0.11</version>
   </dependency>
   <!-- REST API -->
   <dependency>
      <groupId>com.github.paulcwarren</groupId>
      <artifactId>spring-content-rest-boot-starter</artifactId>
      <version>0.0.11</version>
   </dependency>
  

Entity.java

@Entity
public class Entity {
   @Id
   @GeneratedValue
   private long id;

   @ContentId
   private String contentId;

   @ContentLength
   private long contentLength = 0L;

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

DataContentStore.java

@StoreRestResource(path="data")
public interface DataContentStore extends ContentStore<Data, String> {
}

答案 3 :(得分:0)

您可以使用Hibernate.getLobCreator并通过一条语句(下面的4条)并通过EntityManager可以打开的会话传递给您:

// 1. Get entity manager and repository
EntityManager em = .... // get/inject someway the EntityManager
EntityRepository repository = ...// get/inject your Entity repository

// 2. Instantiate your Entity
Entity entity = new Entity();

// 3. Get an input stream (you shall also know its length)
File inFile = new File("/somepath/somefile");
InputStream inStream = new FileInputStream(inFile);

// 4. Now copy to the BLOB
Blob blob =
  Hibernate.getLobCreator(em.unwrap(Session.class))
           .createBlob(inStream, inFile.length());

// 5. And finally save the BLOB
entity.setBlob(blob);
entityRepository.save(f);

答案 4 :(得分:0)

您还可以直接从Blob创建DataSource

@Component
public class LobHelper {

    private final DataSource ds;

    public LobHelper(@Autowired DataSource ds){
         this.ds = ds;
    }

    public Blob createBlob(byte[] content) {
        try (Connection conn = ds.getConnection()) {
            Blob b = conn.createBlob();
            try (OutputStream os = b.setBinaryStream(1);
                 InputStream is = new ByteArrayInputStream(content)) {
                byte[] buffer = new byte[500000];
                int len;
                while ((len = is.read(buffer)) > 0) {
                    os.write(buffer, 0, len);
                }
                return b;
            }
        } catch (Exception e) {
            log.error("Error while creating blob.", e);
        }
        return null;
    }

}

答案 5 :(得分:0)

我在获取当前会话工厂方面遇到了一些问题,例如上面的答案(例如,出现了类似Could not obtain transaction-synchronized Session for current thread的错误)。最后(在Spring Boot应用程序中,当前版本为2.3.1.RELEASE,Hibernate 5.4.1)使用以下方法,并且我的问题已解决。

@Component
public class SomeService {

    /**
     * inject entity manager
     */
    @PersistenceContext 
    private EntityManager entityManager;

    @Transactional
    public void storeMethod(File file) {
       // ...
       FileInputStream in = new FileInputStream(file);

       Session session = entityManager.unwrap(Session.class);
       Blob blob = session.getLobHelper().createBlob(in, file.length());
       // ...
       entity.setData(blob);
       repo.save(entity);
    }
}