【问题标题】:Hibernate JOIN fetch also related entitiesHibernate JOIN 也获取相关实体
【发布时间】:2017-06-27 13:19:59
【问题描述】:

我正在使用 Spring Data REST,Hibernate 5.2.10。这是我的模型:

    @Entity
    public class WorkSession extends AbstractEntity {
    private static final long serialVersionUID = -5058296954283517829L;

    @NotNull(message = "The user is mandatory")
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private User agent;

    @NotNull(message = "The checkpoint is mandatory")
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private CheckPoint checkPoint;

    @Column(nullable = false, updatable = false)
    private LocalDateTime startDate = LocalDateTime.now();

    private LocalDateTime endDate;

    @Lob
    private String notes;

    public WorkSession() {  
    }

和用户:

@Entity
public class User extends AbstractEntity implements UserDetails {
    private static final long serialVersionUID = 5745401123028683585L;
    public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();

    @NotNull(message = "The name of the user cannot be blank")
    @Column(nullable = false)
    private String name;

    /** CONTACT INFORMATION **/
    private String landlinePhone;

    private String mobilePhone;

    @NotNull(message = "The username cannot be blank")
    @Column(nullable = false, unique = true)
    private String username;

    @Email(message = "The email address is not valid")
    private String email;

    @JsonIgnore
    private String password;

    @Column(nullable = false)
    private String timeZone = "Europe/Rome";        

    @JsonIgnore
    private LocalDateTime lastPasswordResetDate;

    @Column(nullable = false, columnDefinition = "BOOLEAN default true")
    private boolean enabled = true;

    @Type(type = "json")
    @Column(columnDefinition = "json")
    private String[] roles = new String[] {};

在我的一项服务中,我正在创建此查询:

@RestResource(rel = "findActiveWorkSessionForUser", path = "findActiveWorkSessionForUser")
@Query("SELECT ws FROM WorkSession ws JOIN ws.agent u WHERE u.username= ?#{principal.username} AND ws.endDate IS NULL")
@Transactional(readOnly = true)
public List<WorkSession> findByAgentUsernameAndEndDateIsNull();

这个存储库是通过 Spring Data REST 公开的,当我调用这个端点时,结果还包含嵌套对象 User,就像你在这里看到的那样:

`{
  "_embedded": {
    "workSessions": [
      {
        "sid": "ed9f01d0-f18d-491b-aad9-4445d457d7eb",
        "createdDate": "2017-06-27T13:13:24",
        "lastModifiedDate": "2017-06-27T13:13:24",
        "lastModifiedBy": "admin",
        "startDate": "2017-06-27T13:13:24",
        "endDate": null,
        "notes": null,
        "new": false,
        "_embedded": {
          "agent": {
            "name": "Administrator",
            "roles": [
              "ROLE_ADMIN"
            ],
            "username": "admin",
            "activeWorkSession": "",
            "_links": {
              "self": {
                "href": "http://localhost:8080/api/v1/users/1{?projection}",
                "templated": true
              }
            }
          }
        },
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/v1/workSessions/1"
          },
          "workSession": {
            "href": "http://localhost:8080/api/v1/workSessions/1"
          },
          "checkPoint": {
            "href": "http://localhost:8080/api/v1/workSessions/1/checkPoint"
          },
          "agent": {
            "href": "http://localhost:8080/api/v1/workSessions/1/agent"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/v1/workSessions/search/findActiveWorkSessionForUser"
    }
  }
}`

我想避免这种情况(实际上该字段在我的配置中是 LAZY 的)。有没有办法避免这种行为?

【问题讨论】:

  • 我相信这是因为您在 jpa 查询中使用 join 关键字获取代理。尝试这样的本机查询,它可能会避免您的问题。 @Query("SELECT ws.* FROM WorkSession ws JOIN User u on u.user_uid = ws.user_uid WHERE u.username= ?#{principal.username} AND ws.endDate IS NULL", nativeQuery = true)
  • 请尝试以下操作 - 省略 JOIN ws.agent 但保留 WHERE 子句。它应该可以解决问题。有效吗?
  • @ArtemNovikov 不幸的是不起作用。它加载嵌套对象。
  • @Sudhakar 看起来很奇怪,但也会对发送的嵌入对象进行本机查询。

标签: java spring hibernate spring-data-rest


【解决方案1】:

您可以通过在 User 上添加 JsonProperty 访问来防止 JSON 序列化。

@JsonProperty(access=WRITE_ONLY)

在此处查看更多信息:https://fasterxml.github.io/jackson-annotations/javadoc/2.6/com/fasterxml/jackson/annotation/JsonProperty.Access.html

【讨论】:

  • 不幸的是,Json 标签不适用于 Spring Data REST。
  • 为什么不呢?你 pojo 必须以某种方式转换为 json
  • 可能是我的错,这是 Spring Data REST 以前版本的一个错误。无论如何,它在我的情况下不起作用,但是我一直在寻找解决特定问题的方法,而不是始终禁用该属性的序列化的方法。谢谢
  • 在返回之前拦截并删除用户呢?
  • 我应该实现失去 Spring Data REST 优势的方法。
【解决方案2】:

WorkSession 中,您可以使用@JsonIgnore 注释User 字段

@JsonIgnore
@NotNull(message = "The user is mandatory")
@ManyToOne(fetch = FetchType.LAZY, optional = false)
private User agent;

JSON 序列化框架不会调用导致加载用户对象的代理字段的getter

【讨论】:

  • 感谢您的回复。我并不是一直在寻找一种方法来忽略该属性,而只是在我的存储库中的那个查询中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 1970-01-01
  • 2013-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多