什么是最好的"或使用spring-data-jpa存储blob实体的规范方法?
dx
答案 0 :(得分:7)
您可以看到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();
}
@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);
}
}