我如何使JPA实体领域真正地写

发布于 2025-02-06 17:36:39 字数 724 浏览 2 评论 0 原文

我有一种情况,我将大型 JSONB 字段持续到Postgres表中,但是当我获取实体时不想阅读它;如果我确实获取它,我的服务就会糟糕。一个更好的设计可能是将其分为1比1表,但目前我不能这样做。

为了说这不是一个重复的问题,这是我的一些研究:

  1. 我无法标记列懒惰,因为我有一个简单的列而不是加入`` jpa/hibernate仅写入字段,没有阅读
  2. 我尝试了在此建议中,空的设置器是有道理的 - 但它似乎仍然读了列,而我却是:
  3. ​> @data class:省略Lombok中的一个setter/getter

因此,我看不到该字段,但是我似乎无法在后台阅读记忆。似乎在JPA或Hibernate中必须有一些简单的设置才能排除Read的列。在我尝试制作复杂的存储库层次结构之前,只是看看它是否有效,我想我会在这里问我很幸运。

提前致谢!

I have a case where I'm persisting a large jsonb field into a PostGres table, but do not want to read it when I fetch the entity; if I do fetch it, my service goes OOM. A better design might be to separate this into a 1 to 1 table, but I can't do that at this time.

To plead that this is not a duplicate question, here's some of my research:

  1. I'm not able to mark the column LAZY since I have a simple column not a join`
    JPA/Hibernate write only field with no read
  2. I tried the empty setter in this suggestion, which makes sense - but it still appears to read the column and I OOM: https://www.zizka.ch/pages/programming/java/hibernate/hibernate-write-only.html
  3. I also tried omitting the setter altogether in my @Data class: Omitting one Setter/Getter in Lombok

So, I can not see the field, but I can't seem to keep it from being read into memory in the background. It seems like there must be some simple setting in JPA or Hibernate to exclude a column from read. Before I go try to make a complex repository hierarchy just to see if it works, I thought I would ask here in case I get lucky.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅忆 2025-02-13 17:36:39

懒负荷属性

Hibernate ,但是您需要启用字节代码增强功能:

  1. 首先,您需要设置属性 hibernate.enhancer.enablelazyInitialization true

  2. ,然后您可以使用 @basic(fetch = fetchype.lazy.lazy)对字段进行注释。
    这是文档中的示例:

     @entity
    公共班级客户{
    
      @ID
      私人整数ID;
    
      私有字符串名称;
    
      @basic(fetch = fetchype.lazy)
      私有UUID帐户SpayableXrefid;
    
      @高球
      @basic(fetch = fetchype.lazy)
      @LazyGroup(“ lob”)
      私人斑点图像;
    
      //为简洁而省略了Getters和Setter
    }
     

You can also enable this feature via the Hibernate orm gradle插件

命名为本机疑问,

您也可以决定不映射它并用一个命名的本地查询。单个属性似乎是一个很好的权衡 - 它将只需要额外的查询即可保存JSON。

示例:

@Entity
@Table(name = "MyEntity_table")
@NamedNativeQuery(
    name = "write_json",
    query = "update MyEntity_table set json_column = :json where id = :id")
@NamedNativeQuery(
    name = "read_json",
    query = "select json_column from MyEntity_table where id = :id")
class MyEntity {
....
}

Long id = ...
String jsonString = ...
session.createNamedQuery( "write_json" )
    .setParameter( "id", id )
    .setParameter( "json", jsonString )
    .executeUpdate();

jsonString = (String)session.createNamedQuery( "read_json" )
    .setParameter( "id", id )
    .getSingleResult();

在这种情况下,模式生成不会创建列,因此您需要手动添加它(考虑到有更好的工具可以更新生产中的模式)。

映射的superClass

您还可以拥有(这样,您不必复制属性)。他们必须更新同一表:

@MappedSuperclass
class MyEntity {

   @Id
   Long id;
   String name
   ...
}

@Entity
@Table(name = "MyEntity_table")
class MyEntityWriter extends MyEntity {

   String json
}

@Entity
@Table(name = "MyEntity_table")
class MyEntityReader extends MyEntity {
   // No field is necessary here
}

现在,您可以使用 myentityWriter 保存所有值和 myentityReader 仅加载所需的值。

我认为,如果您尝试创建表格,则您将在架构生成方面遇到一些问题,因为只会创建两者中的一个:

  • 如果 myentityWriter 是创建的 first 表,则 没问题
  • 如果 myentityWriter second 表创建的,则该查询将失败,因为该表已经存在并且不会创建附加列,因此

。不过,我还没有测试过此解决方案,可能有一些我没有考虑的东西。

Lazy loading attributes

Hibernate can load attribute lazily, but you need to enable byte code enhancements:

  1. First you need to set the property hibernate.enhancer.enableLazyInitialization to true

  2. Then you can annotate the field with @Basic( fetch = FetchType.LAZY ).
    Here's the example from the documentation:

    @Entity
    public class Customer {
    
      @Id
      private Integer id;
    
      private String name;
    
      @Basic( fetch = FetchType.LAZY )
      private UUID accountsPayableXrefId;
    
      @Lob
      @Basic( fetch = FetchType.LAZY )
      @LazyGroup( "lobs" )
      private Blob image;
    
      //Getters and setters are omitted for brevity
    }
    

You can also enable this feature via the Hibernate ORM gradle plugin

Named Native queries

You could also decide to not map it and save/read it with a named native query. It seems a good trade off for a single attribute - it will just require an additional query to save the json.

Example:

@Entity
@Table(name = "MyEntity_table")
@NamedNativeQuery(
    name = "write_json",
    query = "update MyEntity_table set json_column = :json where id = :id")
@NamedNativeQuery(
    name = "read_json",
    query = "select json_column from MyEntity_table where id = :id")
class MyEntity {
....
}

Long id = ...
String jsonString = ...
session.createNamedQuery( "write_json" )
    .setParameter( "id", id )
    .setParameter( "json", jsonString )
    .executeUpdate();

jsonString = (String)session.createNamedQuery( "read_json" )
    .setParameter( "id", id )
    .getSingleResult();

In this case, schema generation is not going to create the column, so you will need to add it manually (not a big deal, considering that there are better tools to update the schema in production).

MappedSuperclass

You can also have two entities extending the same superclass (this way you don't have to copy the attributes). They have to update the same table:

@MappedSuperclass
class MyEntity {

   @Id
   Long id;
   String name
   ...
}

@Entity
@Table(name = "MyEntity_table")
class MyEntityWriter extends MyEntity {

   String json
}

@Entity
@Table(name = "MyEntity_table")
class MyEntityReader extends MyEntity {
   // No field is necessary here
}

Now you can use MyEntityWriter for saving all the values and MyEntityReader for loading only the values you need.

I think you will have some problems with schema generation if you try to create the tables because only one of the two will be created:

  • If MyEntityWriter is the first table created, then no problem
  • If MyEntityWriter is the second table created, the query will fail because the table already exist and the additional column won't be created.

I haven't tested this solution though, there might be something I haven't thought about.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文