带有 Postgres 的 JPA 异常地将文本作为数字写入 @Lob 列
JPA with Postgres anomalously writes text in @Lob column as a number
我正在尝试使用具有 Java String
类型的 @Lob
列将其内容映射到 Postgres 中的 TEXT
。这是相关实体:
@Entity(name="metadata")
public class Metadata {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "created_on")
@ColumnDefault(value="CURRENT_TIMESTAMP")
@Generated(GenerationTime.INSERT)
private LocalDateTime createdOn;
@Lob
@Column(name = "content")
private String content;
@Column(name = "draft")
private Boolean draft;
@OneToMany(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "metadata")
private List<Attachment> attachments;
public void addAttachment(Attachment attachment) {
if (attachments == null) {
attachments = new ArrayList<>();
}
attachments.add(attachment);
attachment.setMetadata(this);
}
// getters and setters
}
我有代码可以根据使用输入创建一个新的 Metadata
实体。我在 IntelliJ 调试模式下手动验证此实体已将 content
设置为其预期值(恰好是 JSON 字符串)。但是,当我在 运行 代码之后检查 Postgres 时,我看到了这个数据:
my_db=> select * from metadata;
id | content | created_on | draft
----+---------+-------------------------+-------
1 | 49289 | 2021-04-26 14:21:25.733 | t
(1 row)
请仔细注意,奇怪的值 49289
出现在我们期望看到 JSON 字符串的位置。请注意,我还从命令行验证了正确的 table 是创建的内容:
CREATE TABLE scarfon_attachment (
id bigint NOT NULL,
contents text,
filename character varying(255),
scarfon_id bigint NOT NULL
);
entity/table 中的所有其他列都按预期工作。 @Lob
注释可能有什么问题。作为参考,我是 运行 相当旧的 Postgres (9.2) 版本,但它并没有那么古老。
当使用 @Lob
时,Hibernate ORM 将期望数据库中有一个 text
类型的列,您可以使用它保存最大 1 Gb 的文本文件。
您可以避免使用它,它会将列的类型更改为 VARCHAR(255)
。
不同之处在于,您可以限制 VARCHAR
的大小,ORM 默认为 255,但不能限制 text
.
的大小
您还可以更改默认列类型(我认为 varchar 可以大到 1Gb):
@Column(name = "content", columnDefinition = "varchar(500)")
String content
因此,最终使用哪种方法取决于您。我假设对于大字符串 text
更好,但您需要评估您的用例。
我的第一个疑问是许多消息来源提出了创建 TEXT
列的多种方法。例如,this Baeldung post 建议使用 @Lob
除了使用带有 @Column
注释的定义。
事实证明,@Lob
并不是所有数据库都以相同的方式解释。在 Postgres 的情况下,仅使用 @Lob
将导致 Postgres 将列内容存储在 不同的 table 中,该列用 [=12= 注释] 只是为 table 中的每个条目存储一个 ID。虽然有人建议 here 通过 @Type
注释指定正确的类型也可以解决这个问题,但我决定采用 Baledung post 的第二个建议,它使用 @Column
:
@Lob
@Column(columnDefinition="TEXT")
private String content;
这工作正常,并且生成的 Postgres table 具有预期的 TEXT
定义。上述问题的唯一潜在问题可能集中在与其他 SQL 数据库的可移植性上,这些数据库可能不支持 TEXT
类型,或者可能支持某些替代方案。我没有在 Postgres 和 H2 之外进行测试,但在这两种情况下,以上都没有问题。
我正在尝试使用具有 Java String
类型的 @Lob
列将其内容映射到 Postgres 中的 TEXT
。这是相关实体:
@Entity(name="metadata")
public class Metadata {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "created_on")
@ColumnDefault(value="CURRENT_TIMESTAMP")
@Generated(GenerationTime.INSERT)
private LocalDateTime createdOn;
@Lob
@Column(name = "content")
private String content;
@Column(name = "draft")
private Boolean draft;
@OneToMany(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "metadata")
private List<Attachment> attachments;
public void addAttachment(Attachment attachment) {
if (attachments == null) {
attachments = new ArrayList<>();
}
attachments.add(attachment);
attachment.setMetadata(this);
}
// getters and setters
}
我有代码可以根据使用输入创建一个新的 Metadata
实体。我在 IntelliJ 调试模式下手动验证此实体已将 content
设置为其预期值(恰好是 JSON 字符串)。但是,当我在 运行 代码之后检查 Postgres 时,我看到了这个数据:
my_db=> select * from metadata;
id | content | created_on | draft
----+---------+-------------------------+-------
1 | 49289 | 2021-04-26 14:21:25.733 | t
(1 row)
请仔细注意,奇怪的值 49289
出现在我们期望看到 JSON 字符串的位置。请注意,我还从命令行验证了正确的 table 是创建的内容:
CREATE TABLE scarfon_attachment (
id bigint NOT NULL,
contents text,
filename character varying(255),
scarfon_id bigint NOT NULL
);
entity/table 中的所有其他列都按预期工作。 @Lob
注释可能有什么问题。作为参考,我是 运行 相当旧的 Postgres (9.2) 版本,但它并没有那么古老。
当使用 @Lob
时,Hibernate ORM 将期望数据库中有一个 text
类型的列,您可以使用它保存最大 1 Gb 的文本文件。
您可以避免使用它,它会将列的类型更改为 VARCHAR(255)
。
不同之处在于,您可以限制 VARCHAR
的大小,ORM 默认为 255,但不能限制 text
.
您还可以更改默认列类型(我认为 varchar 可以大到 1Gb):
@Column(name = "content", columnDefinition = "varchar(500)")
String content
因此,最终使用哪种方法取决于您。我假设对于大字符串 text
更好,但您需要评估您的用例。
我的第一个疑问是许多消息来源提出了创建 TEXT
列的多种方法。例如,this Baeldung post 建议使用 @Lob
除了使用带有 @Column
注释的定义。
事实证明,@Lob
并不是所有数据库都以相同的方式解释。在 Postgres 的情况下,仅使用 @Lob
将导致 Postgres 将列内容存储在 不同的 table 中,该列用 [=12= 注释] 只是为 table 中的每个条目存储一个 ID。虽然有人建议 here 通过 @Type
注释指定正确的类型也可以解决这个问题,但我决定采用 Baledung post 的第二个建议,它使用 @Column
:
@Lob
@Column(columnDefinition="TEXT")
private String content;
这工作正常,并且生成的 Postgres table 具有预期的 TEXT
定义。上述问题的唯一潜在问题可能集中在与其他 SQL 数据库的可移植性上,这些数据库可能不支持 TEXT
类型,或者可能支持某些替代方案。我没有在 Postgres 和 H2 之外进行测试,但在这两种情况下,以上都没有问题。