将Spring Native查询中的新列映射到实体

时间:2018-03-27 20:44:19

标签: spring spring-data-jpa entity jpa-2.1

我的Native查询中有一个case语句,我试图覆盖实体中的一个字段。

SELECT i.id, i.ONE_TO_ONE_ID, i.ANOTHER, CASE(WHEN condition THEN 'YES' WHEN another_condition THEN 'NO' ELSE 'MAYBE' END) as word ....

我使用JpaRepository作为本机查询,并使用分页。

当我直接对我的db运行本机查询时,结果集看起来就像我期望的那样。

| id_value | MAPPED_ENTITY_ID_value | another value | word_value (YES) |

当我从JpaRepository运行本机查询时,一切都在那里工作,除了word总是为null。我不能'似乎弄清楚如何将附加的String word结果映射到我的Entity中的字段。

有没有办法让它映射?或者我是否必须为我的所有字段和本机查询创建一个完整的@SqlResultSetMapping()? (希望不是)

更新:1

我在上面概括。这是我的查询。

@Query(
            name = "listPagedMapping",
            value = "SELECT DISTINCT i.ID, i.INSTANCE_ID, i.REGION, i.CNAME_STACK_ID, i.INSTANCE_STATE, i.IP_ADDRESS, i.EC2_ROLE_NAME, i.INSTANCE_OWNER, i.IS_MASTER, i.EC2_MASTER_ID, i.CNAME, i.EC2_START_TIMESTAMP, i.PRIVATE_DNS, i.INSTANCE_NAME, i.AUTO_TERMINATE, i.AUTO_TERMINATE_DATE, i.TERMINATION_ZONE, i.ADMIN_GROUP_AD_LDAP_ID, i.USER_GROUP_AD_LDAP_ID,  (CASE WHEN i.INSTANCE_OWNER=:username THEN 'OWNER' WHEN i.ADMIN_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) THEN 'ADMIN' WHEN  i.USER_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) THEN 'USER' END) as PERMISSION FROM USER u, USER_ACCESS_GROUPS g, EC2_PROVISIONING i WHERE i.INSTANCE_OWNER=:username and i.INSTANCE_STATE in (:instanceStates) or u.username=:username and i.INSTANCE_STATE in (:instanceStates) and g.USER_ID=u.USER_ID and (i.ADMIN_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) or i.USER_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID))",
            countQuery = "SELECT count(*) FROM (SELECT DISTINCT i.* FROM USER u, USER_ACCESS_GROUPS g, EC2_PROVISIONING i WHERE i.INSTANCE_OWNER=:username and i.INSTANCE_STATE in (:instanceStates) or u.username=:username and i.INSTANCE_STATE in (:instanceStates) and g.USER_ID=u.USER_ID and (i.ADMIN_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID) or i.USER_GROUP_AD_LDAP_ID IN (g.AD_LDAP_ID))) as ug",
            nativeQuery = true)
    Page<Ec2Instance> findAllByPermissionUserAdminOrOwnerAndInstanceStateIn(
            @Param("username")final String username,
            @Param("instanceStates") final Set<String> instanceStates,
            final Pageable pageable);

}

显然有点复杂。

我可以使用命名查询将其映射到实体字段,但随后我将丢失所有默认映射:

@JsonInclude(JsonInclude.Include.NON_NULL)
@SuppressWarnings("unused")
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(exclude={"masterNode", "workers", "associatedBuckets"})
@Entity
@Table(name = "EC2_PROVISIONING")
@SqlResultSetMapping(
        name="listPagedMapping",
        columns = {
                @ColumnResult(name = "permission", type = String.class)
        }
)
@NamedNativeQuery(
        name = "listAccessibleInstances",
        query = ACCESSIBLE_QUERY,
        resultSetMapping = "listPagedMapping"

)
public class Ec2Instance {

    ....

    private String permission;

    @column(name = "INSTANCE_ID")
    private String instanceId;

    @ManyToOne
    @JoinColumn(name = "EC2_MASTER_ID")
    private Ec2Instance masterNode;

        @Setter(AccessLevel.NONE)
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "WORKER_EC2_NODES", joinColumns = { @JoinColumn(name = "EC2_MASTER_ID") }, inverseJoinColumns = {
            @JoinColumn(name = "ID") })
    private Set<Ec2Instance> workers = new HashSet<>();

    ... More fields ..

}

我想,我希望有一种方法可以在ORM完成的默认映射之上提供单个映射。上面的代码只导致Content PERMISSION的可分页,而不是整个实体+权限。

更新:2

好的,所以我越来越近了......似乎删除了@ColumnResult我得到了默认的映射,加上映射的PERMISSION字段!看起来像这样:

@SqlResultSetMapping(
        name="listPagedMapping"
)

最后一个问题是它不接受我的CountQuery,并且每当分页查询产生多个页面时,我的测试都会失败。看起来Spring尝试提出自己的CountQuery,这是不正确的。

更新:3

要完成此操作,看起来我可以按照此处所述提供计数查询:Spring Data - Why it's not possible to have paging with native query

我会先试试并更新回来。

1 个答案:

答案 0 :(得分:0)

我从来没有按照我想要的方式工作。我相信我可以通过映射我的整个实体,但是,这本来是艰苦的。我最后通过使用NamedNativeQueries解决了这个问题,并在我的Case语句中使用了附加列的映射。我的实体类现在注释如下:

docker exec -i -t <container_name> bash

我们也不再需要此实体中的权限字段。我删除了。

然后在我的存储库中:

@JsonInclude(JsonInclude.Include.NON_NULL)
@SuppressWarnings("unused")
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Entity
@Table(name = "EC2_PROVISIONING")
@SqlResultSetMappings({
        @SqlResultSetMapping(
                name = "listPagedMapping",
                entities = {
                        @EntityResult(
                                entityClass = Ec2Instance.class
                        )
                },
                columns = {@ColumnResult(name = "permission", type = String.class)}
        ),
        @SqlResultSetMapping(name = "listPagedMapping.count", columns = @ColumnResult(name = "cnt"))
})
@NamedNativeQueries({
    @NamedNativeQuery(
            name = "Ec2Instance.listAccessibleInstances",
            query = ACCESSIBLE_QUERY,
            resultClass = Ec2Instance.class,
            resultSetMapping = "listPagedMapping"
    ),
    @NamedNativeQuery(
            name = "Ec2Instance.listAccessibleInstances.count",
            resultSetMapping = "listPagedMapping.count",
            query = ACCESSIBLE_QUERY_COUNT
    )
})

多数民众赞成!现在,我的case语句的结果随每个实体一起返回。

Object [0] =原始,默认映射实体。 对象[1] =权限