使用 jpa 从 postgres 读取 byte[] 时,长度几乎增加了一倍
我有一个 Image 类,它有一个 byte[] 来包含实际的图像数据。我可以在我的网络应用程序中上传和插入图像。当我尝试从 JPA 读取图像后显示图像时,我的 byte[] 的长度始终为 2x-1 或 2x-2,其中 x 是 postgres 9 中 bytea 字段的长度。显然浏览器不会显示图像说它已损坏。我需要一些帮助来弄清楚为什么我得到的结果是我预期的两倍。这是我的图像类的映射。在 Mac 上使用 eclipselink 和 JPA 2 来访问 postgres 9。
当我从数据库中选择时,
select *, length(bytes) from image;
我得到的长度为 9765。在控制器的断点中,byte[] 长度为 19529,比数据库中的两倍少一个字节。
@Entity
@Table( name = "image" )
@SequenceGenerator( name = "IMAGE_SEQ_GEN", sequenceName = "IMAGE_SEQUENCE" )
public class Image
extends DataObjectAbstract<Long>
{
@Id
@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "IMAGE_SEQ_GEN" )
private Long key;
@Column( name="content_type" )
private String contentType;
@Lob
@Basic( optional=false )
@Column( name="bytes" )
private byte[] bytes;
// constructor and getters and setters
}
pgadmin 向我展示了以下图像表
CREATE TABLE image
(
"key" bigint NOT NULL,
bytes bytea,
content_type character varying(255),
"version" integer,
CONSTRAINT image_pkey PRIMARY KEY (key)
)
WITH (
OIDS=FALSE
);
I have an Image class that has a byte[] to contain the actual image data. I'm able to upload and insert the image just fine in my webapp. When I attempt to display the image after reading it from JPA the length of my byte[] is always either 2x-1 or 2x-2, where x is the length of the bytea field in postgres 9. Obviously the browser won't display the image saying it's corrupted. I could use some help figuring out why I'm getting (about) twice what I expect. Here's the mapping of my image class. Using eclipselink with JPA 2 hitting postgres 9 on a mac.
When I select from the database with
select *, length(bytes) from image;
I get a length of 9765. In a breakpoint in my controller the byte[] length is 19529 which is one byte shy of twice what's in the database.
@Entity
@Table( name = "image" )
@SequenceGenerator( name = "IMAGE_SEQ_GEN", sequenceName = "IMAGE_SEQUENCE" )
public class Image
extends DataObjectAbstract<Long>
{
@Id
@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "IMAGE_SEQ_GEN" )
private Long key;
@Column( name="content_type" )
private String contentType;
@Lob
@Basic( optional=false )
@Column( name="bytes" )
private byte[] bytes;
// constructor and getters and setters
}
pgadmin shows me the following for the image table
CREATE TABLE image
(
"key" bigint NOT NULL,
bytes bytea,
content_type character varying(255),
"version" integer,
CONSTRAINT image_pkey PRIMARY KEY (key)
)
WITH (
OIDS=FALSE
);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
“bytea_output = escape”只是一个解决方法,Postgres 8.0 将 bytea 编码更改为十六进制。
使用 9.0-dev800 以来的最新 JDBC 驱动程序(9.0 Build 801 目前是最新的),问题将得到解决。
The "bytea_output = escape" is just a workaround, Postgres 8.0 changed the bytea encoding to hex.
Use a current JDBC driver since 9.0-dev800 (9.0 Build 801 is up-to-date currently) and the problem will be solved.
在 PostgreSQL 9 中,byte[] 使用十六进制编码发送到客户端。
如果这是错误的原因,您必须找到 JPA 的更新。
或者您可以更改数据库服务器的配置,但以前的配置更好。
In PostgreSQL 9 byte[] is sent to client using hex encoding.
If this is reason for error you have to find update for JPA.
Or you may change config of DB server but previous is better.
GlassFish 3.x 用户的补充答案(原则可能适用于其他应用服务器)
您可能无意中使用了旧的 PostgreSQL JDBC 驱动程序。您可以通过在某处(例如 EJB)注入
DataSource
并对其执行以下命令来测试这一点:System.out.println(ds.getConnection().getMetaData().getDriverVersion() );
就我而言,它是 8.3,这是意外的,因为我使用 9.1 驱动程序进行部署。
要找出它来自哪里:
System.out.println(Class.forName("org.postgresql.Driver").getProtectionDomain().getCodeSource().getLocation());
结果对我来说,它位于我的 GlassFish 域的 lib 目录中。我不确定它是如何到达那里的 - GlassFish 肯定不会以这种方式发送 - 所以我只是将其删除,问题就消失了。
Supplementary answer for GlassFish 3.x users (principles may apply to other app servers)
You may be inadvertently using an old PostgreSQL JDBC driver. You can test this by injecting a
DataSource
somewhere (e.g. an EJB) and executing the following on it:System.out.println(ds.getConnection().getMetaData().getDriverVersion());
In my case, it was 8.3 which was unexpected since I was deploying with 9.1 drivers.
To find out where this was coming from:
System.out.println(Class.forName("org.postgresql.Driver").getProtectionDomain().getCodeSource().getLocation());
As it turned out for me, it was in the lib directory of my GlassFish domain. I'm not sure how it got there - GlassFish certainly doesn't ship that way - so I just removed it and the problem went away.
尝试查看您获得的数据。它可能会给您提供有关正在发生的事情的线索。
Try looking at the data you're getting. It may give you a clue as to what's happening.
检查您是否有旧的 postgresql jar。我遇到了同样的问题,并在我的库中发现了 8.3 postgresql jar 和 9.1 postgresql jar 。删除 8.3 postgresql 后,byte[] 工作正常。
Check whether you have an old postgresql jar. I faced the same problem, and found both 8.3 postgresql jar and a 9.1 postgresql jar in my lib. After remove 8.3 postgresql, byte[] works fine.