如何通过 EntityManager 从 InputStream 更新 BLOB?
How can I update a BLOB from an InputStream via an EntityManager?
我有一个 table:
mysql> desc documents;
+---------+--------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| item_id | int(11) | YES | MUL | NULL | |
| doctype | int(11) | YES | MUL | NULL | |
| name | varchar(128) | YES | MUL | NULL | |
| descr | text | YES | | NULL | |
| created | timestamp | NO | | CURRENT_TIMESTAMP | |
| changed | timestamp | NO | | 0000-00-00 00:00:00 | |
| doc | longblob | YES | | NULL | |
+---------+--------------+------+-----+---------------------+----------------+
我已将其映射为 Entity
,如下所示:
@Entity
@Table(name = "documents", schema = "office_db")
@XmlRootElement
@NamedQueries({
...,
@NamedQuery(name = "Documents.updateDocById", query = "UPDATE Documents d SET d.doc = :document WHERE d.id = :id")
})
public class Documents implements Serializable {
@Column(name = "name", length = 128)
private String name;
@Lob
@Column(name = "descr", length = 65535)
private String descr;
@Lob
@Column(name = "doc")
private byte[] doc;
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@Column(name = "created")
@Temporal(TemporalType.TIMESTAMP)
private Date created;
@Basic(optional = false)
@Column(name = "changed")
@Temporal(TemporalType.TIMESTAMP)
private Date changed;
...
}
我想用文件的内容更新 LONGBLOB DOC 列。为此,我获得了一个 InputStream
并想将它与我的 NamedQuery
相关联 - 我天真地尝试了以下操作,并期望它会失败(当然它会失败):
public String updateDocument(Integer id,InputStream is){
String msg="";
try{
Query stmt=em.createNamedQuery("Documents.updateDocById")
.setParameter("document",is);
stmt.executeUpdate();
}
...
}
如果我使用 PreparedStatement
,我可以使用 setBinaryStream
方法,但那真的是正确的方法吗?
因此,回答我自己的问题:根据 What’s new in JPA 2.2 – Stream the result of a Query execution | Vlad Mihalcea's Blog,JPA 似乎不支持流式传输,至少在 JPA 2.2 之前不支持 - 看起来它仅用于流式传输查询结果,而不是更新 BLOB,这正是我要找的。
看起来又回到了使用 PreparedStatement
和 setBinaryStream()
的状态。我还没有尝试过,但是基于 How to get DataSource or Connection from JPA2 EntityManager in Java EE 6,我的策略是:
- 开始交易。
- 从
EntityManager
. 中提取连接
- 创建
PreparedStatement
.
- ...
- 提交或回滚事务。
我觉得有点恶心,但你就是这样。
我有一个 table:
mysql> desc documents;
+---------+--------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| item_id | int(11) | YES | MUL | NULL | |
| doctype | int(11) | YES | MUL | NULL | |
| name | varchar(128) | YES | MUL | NULL | |
| descr | text | YES | | NULL | |
| created | timestamp | NO | | CURRENT_TIMESTAMP | |
| changed | timestamp | NO | | 0000-00-00 00:00:00 | |
| doc | longblob | YES | | NULL | |
+---------+--------------+------+-----+---------------------+----------------+
我已将其映射为 Entity
,如下所示:
@Entity
@Table(name = "documents", schema = "office_db")
@XmlRootElement
@NamedQueries({
...,
@NamedQuery(name = "Documents.updateDocById", query = "UPDATE Documents d SET d.doc = :document WHERE d.id = :id")
})
public class Documents implements Serializable {
@Column(name = "name", length = 128)
private String name;
@Lob
@Column(name = "descr", length = 65535)
private String descr;
@Lob
@Column(name = "doc")
private byte[] doc;
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@Column(name = "created")
@Temporal(TemporalType.TIMESTAMP)
private Date created;
@Basic(optional = false)
@Column(name = "changed")
@Temporal(TemporalType.TIMESTAMP)
private Date changed;
...
}
我想用文件的内容更新 LONGBLOB DOC 列。为此,我获得了一个 InputStream
并想将它与我的 NamedQuery
相关联 - 我天真地尝试了以下操作,并期望它会失败(当然它会失败):
public String updateDocument(Integer id,InputStream is){
String msg="";
try{
Query stmt=em.createNamedQuery("Documents.updateDocById")
.setParameter("document",is);
stmt.executeUpdate();
}
...
}
如果我使用 PreparedStatement
,我可以使用 setBinaryStream
方法,但那真的是正确的方法吗?
因此,回答我自己的问题:根据 What’s new in JPA 2.2 – Stream the result of a Query execution | Vlad Mihalcea's Blog,JPA 似乎不支持流式传输,至少在 JPA 2.2 之前不支持 - 看起来它仅用于流式传输查询结果,而不是更新 BLOB,这正是我要找的。
看起来又回到了使用 PreparedStatement
和 setBinaryStream()
的状态。我还没有尝试过,但是基于 How to get DataSource or Connection from JPA2 EntityManager in Java EE 6,我的策略是:
- 开始交易。
- 从
EntityManager
. 中提取连接
- 创建
PreparedStatement
. - ...
- 提交或回滚事务。
我觉得有点恶心,但你就是这样。