什么是用弹簧数据的JPA存储与BLOB实体“最佳”或规范的方法?
@Entity
public class Entity {
@Id
private Long id;
@Lob()
private Blob blob;
}
public interface Repository extends CrudRepository<Entity, Long> {
}
你可以看到sample project on my github。该项目展示了如何从数据库流数据/。
流 - 关于映射@Lob
为byte[]
击败(IMO)的主要优势斑点的所有建议。随着byte[]
一切都被加载到内存中。可能行,但如果你有LargeObject去,你可能要流。
@Entity
public class MyEntity {
@Lob
private Blob data;
...
}
暴露的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
。
春天的数据不处理的BLOB但Spring Content一样。具体来说,春天内容JPA存储内容,如数据库和内容与实体通过注释同事的BLOB。
pom.hml
<!-- 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";
data content store.Java
@StoreRestResource(path="data")
public interface DataContentStore extends ContentStore<Data, String> {
}
这种方法在接受答案的优势在于,开发者不需要担心任何的样板代码(在接受的答案“服务”)的。斑也暴露春天资源给人一种自然的编程接口。或者,可以通过REST接口自动导出。但是,这一切都不需要任何编码,代表开发的,除了Java的配置和商店界面。
自动装配资源库接口,并呼吁通过你的实体对象的保存方法。
我有一个类似的设置它工作得很好:
@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;
您可以使用Hibernate.getLobCreator和传递一个EntityManager的能解开你的会话一条语句(低于4)做到这一点:
// 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);
您也可以从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;
}
}