【问题标题】:How to make Spring Projections work with @OneToOne relation?如何使 Spring Projections 与 @OneToOne 关系一起工作?
【发布时间】:2020-06-10 20:45:37
【问题描述】:

我正在尝试使用 Spring Projections,但我无法使其工作。我需要 OneToOne 关系是一个投影,所以它就像一个投影内的投影。看起来它会起作用,但是嵌套类没有映射到 Json 中。我的实体:

@Entity(name = "user")
@Data
public class User {
    @Id
    private String id;
    @NotNull
    private LocalDateTime creationDate;
    private LocalDateTime lastLoginDate;
    private LocalDateTime lastPasswordChangeDate;
    private String name;
    @PrimaryKeyJoinColumn
    @OneToOne(cascade = CascadeType.ALL)
    private ProviderCredentials providerCredentials;
    private boolean deleted;
    private String adminAccountId;


@Entity(name = "provider_credentials")
@Data
public class ProviderCredentials {
    @Id
    private String idUser;
    private String loginName;
    @NotNull
    private String password;
    @NotNull
    private long deletedAt;
    private String passwordVersion;
}

预测如下:

public interface SecondaryUserVO {
    String getId();
    String getName();
    LocalDateTime getCreationDate();
    LocalDateTime getLastLoginDate();
    LocalDateTime getLastPasswordChangeDate();
    ProviderCredentialsDTO getProviderCredentials();
}

public interface ProviderCredentialsDTO {
    String getIdUser();
}

最奇怪的是正在执行的 sql 是有道理的。

select
    user0_.id as col_0_0_,
    user0_.name as col_1_0_,
    user0_.creationDate as col_2_0_,
    user0_.lastLoginDate as col_3_0_,
    user0_.lastPasswordChangeDate as col_4_0_,
    providercr1_.idUser as col_5_0_,
    providercr1_.idUser as iduser1_1_,
    providercr1_.deleted_at as deleted_2_1_,
    providercr1_.login_name as login_na3_1_,
    providercr1_.password as password4_1_,
    providercr1_.password_version as password5_1_ 
from
    user user0_ 
left outer join
    provider_credentials providercr1_ 
        on user0_.id=providercr1_.idUser 
where
    user0_.admin_account_id=?

但是json总是:

[
    {
        "creationDate": "2020-06-10T15:55:42.523397",
        "name": "John Lennon",
        "id": "257ef67d-ca9d-48ac-8638-824376ec1cd2"
    }
]

而我想要的是:

[
    {
        "creationDate": "2020-06-10T15:55:42.523397",
        "name": "John Lennon",
        "id": "257ef67d-ca9d-48ac-8638-824376ec1cd2",
        "providerCredentials" : {"idUser" : "257ef67d-ca9d-48ac-8638-824376ec1cd2"}

    }
]

我尝试了不同的方法,但似乎没有任何效果。按照 Spring 页面上的官方说明进行操作,但没有成功。

【问题讨论】:

  • 我意识到如果我使用@Value("#{target.providerCredentials}") 它可以工作,但是它会产生很多不必要的sql查询,所以它仍然没有像我预期的那样工作。

标签: java spring spring-data-jpa projection


【解决方案1】:

您可以在 JPQL 查询中使用 Dto。下面是一个简单的例子。

@Entity
@Data
public class User {
    @Id
    private Long id;
    private String name;
    @OneToOne
    private Creds creds;
}

@Entity
@Data
public class Creds {
    @Id
    private Long id;
    private String password;
}

// if you need projection like this
@Data
public static class UserDto {
    private Long userId;
    private String name;
    private String password;

    public UserDto(Long userId, String name, String password) {
        this.userId = userId;
        this.name = name;
        this.password = password;
    }
}

{
    // this gives you UserDto
    Query query = em.createQuery("select new uz.owl.dto.foo.UserDto(u.id, u.name, c.password) from User u join u.creds c");
}

【讨论】:

  • 我现在正在使用查询,但我更喜欢其他解决方案,但还是谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 2015-01-19
  • 2013-12-26
相关资源
最近更新 更多