【问题标题】:Accessing a Lob property from postgres in the view从视图中的 postgres 访问 Lob 属性
【发布时间】:2013-01-30 11:15:39
【问题描述】:

我有一个标准 Spring Framework (v3.1.2) java (v1.6) 数据库支持 (postgres v9.1) Web 应用程序,它在 Apache Tomcat (v6.0) 上运行。请注意,我使用的是 Hibernate 3.6.10.Final 和 Spring Data JPA 1.2.0.RELEASE。

我有两个数据库实体类——Chapter 和 ChapterText——它们之间是一对一的关系...

@Entity @Table(name="chapter")
public class Chapter implements Comparator<Chapter> {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CHAPTER_SEQ")
    @SequenceGenerator(name="CHAPTER_SEQ", sequenceName="chapter_seq", allocationSize=1)
    @Column(name="id")
    private Long id;

    @OneToOne(cascade=CascadeType.ALL, optional=false, fetch=FetchType.LAZY, orphanRemoval=true) @PrimaryKeyJoinColumn
    private ChapterText chapterText;

    // other properties plus setters and getters
}

@Entity @Table(name="chapterText")
public class ChapterText {

    @Id
    @GeneratedValue(generator="foreign")
    @GenericGenerator(name="foreign", strategy="foreign", parameters={ @Parameter(name="property", value="parent") })
    @Column(name="id")
    private Long id;

    @OneToOne(mappedBy="chapterText", optional=false)
    private Chapter parent;

    @Column(name="body") @Lob
    private String body;

    // setters and getters
}

现在,由于 ChapterText 包含一个 @Lob 属性,它可能包含大量文本,我在 Chapter 类中标记了 chapterText 属性,以便延迟加载。

我已经设置和配置了 OpenEntityManagerInViewFilter,所以我可以向模型添加一个章节实体(名称为“章节”),然后在我的 JSPX 文件中我应该能够做到这一点......

${chapter.chapterText.body}

这应该延迟加载 ChapterText 实体,并在为调用浏览器生成的 XHTML 页面中包含 body 属性的值。

这是从数据库中显示信息的一种完全标准的方式,我已经使用了多年。然而,这是我第一次不得不在 Postgres 中使用 @Lob 属性。当我这样做时,我会看到以下堆栈跟踪...

org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspException: javax.servlet.jsp.JspException: javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
javax.servlet.ServletException: javax.servlet.jsp.JspException: javax.servlet.jsp.JspException: javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
javax.servlet.jsp.JspException: javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
javax.el.ELException: Error reading 'body' on type project.vo.db.ChapterText_$$_javassist_5
.
.
.
org.hibernate.exception.GenericJDBCException: could not load an entity: [project.vo.db.ChapterText#1]
.
.
.
org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.

据我所知,Posgres 需要通过将自动提交设置为 false 的事务来访问要访问的大对象。

令人讨厌的是,我能想到的唯一解决方法是创建一个存储库方法来获取 @Lob 属性,用 @Transactional 标记它并将值加载到专门为显示目的而创建的 bean 中.虽然这确实有效,但似乎有点不雅。

有人对替代方法有任何想法吗?

【问题讨论】:

  • 当你说很多文字时,它是多少文字? lob 流媒体接口有用吗?还是一次性检索所有接口?
  • 您找到解决方案了吗?
  • 不幸的是,我找不到解决方案。最后,我将body属性移到Chapter类中并注解为“@Column(name="chapterBody") @Lob @Basic(fetch=FetchType.LAZY)”

标签: spring hibernate postgresql view lob


【解决方案1】:

首先,我认为您可能需要重新考虑一下您的设计。如果文本小于 1GB,并且您不必在其中查找,那么使用文本字段可能比使用 LOB 更好。这样更容易处理和管理。如果数据在每行 1GB 和 2GB 之间,由于大小的原因,您可能需要使用 LOB。如果您需要能够查询、分块(即按偏移量查找),那么 LOB 是合适的。如果这些都不合适,TEXTBYTEA 字段更可取。请注意,PostgreSQL 会自动将大型属性移动到辅助存储中,因此您不会因为拥有大量内联数据而使扫描速度变慢(基本上,任何超过 4kb 的数据都必须移动到辅助存储中)所以如果这是您的问题,那么我不会担心它。 TEXT 字段更易于管理,因此它们将是我的首选。同样对于文本数据,LOB 的编码使它们对网络流量的影响比 TEXT 字段更糟糕,除非您进行分块。

现在,如果这不可接受,您可以使用 lo_read() 读取 lob 并在您的视图中显示为 bytea

【讨论】:

  • 在某个时候我会考虑重新设计。我想说最大的平均章节是〜100,000字。假设一章中的平均单词有 5/6 个字符,加上空格……那仍然没有接近 1 GB 的数据。
猜你喜欢
  • 2019-08-14
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-10
  • 1970-01-01
相关资源
最近更新 更多