【问题标题】:JPA SqlResultSetMapping to pojo with complex object in attributeJPA SqlResultSetMapping to pojo,属性中具有复杂对象
【发布时间】:2021-11-23 06:00:27
【问题描述】:

我想知道是否有可能(以及它是否是好方法)将 pojo 中本机查询的 sql 结果与其属性中的其他 pojo 映射。 我正在寻找类似的东西:

ResultPojo 类

public class ResultPojo {

    private MyPojo myPojo;
    private Integer firstSimpleAttribute;
    private Integer secondSimpleAttribute;
    private Double thirdSimpleAttribute;
    
    // Empty Constructor + Constructor with fields + Getter + Setter
    
}

MyPojo 类

public class MyPojo {

    private Long id;
    private String label;
    private MySubPojo mySubPojo;
    
    // Empty Constructor + Constructor with fields + Getter + Setter
    
}

MySubPojo 类

public class MySubPojo {

    private String text;
    
    // Empty Constructor + Constructor with fields + Getter + Setter
    
}

映射部分

@SqlResultSetMapping(
    name = "CustomMapping",
    classes={
        @ConstructorResult(
            targetClass=MyPojo.class,
            columns={
                @ColumnResult(name="id", type=Long.class),
                @ColumnResult(name="label", type=String.class),
                @ColumnResult(name="mySubPojo", type=MySubPojo.class)
            }
        )
    },
    columns = {
        @ColumnResult(name = "firstSimpleAttribute", type = Integer.class),
        @ColumnResult(name = "secondSimpleAttribute", type = Integer.class),
        @ColumnResult(name = "thirdSimpleAttribute", type = Double.class)
    }
)

本机查询

Query query = this.entityManager.createNativeQuery(
                    "SELECT r.*, me.id, me.label, mse.*
                     FROM result r 
                         INNER JOIN my_entity me ON r.id_my_entity = me.id_my_entity 
                         INNER JOIN my_sub_entity mse ON me.id_my_sub_entity = mse.id_my_sub_entity",
                    "CustomMapping");

List<Object[]> result = query.getResultList();

// Convert Object[] to List<ResultPojo>

当我这样做时,由于@ColumnResult(name="mySubPojo", type=MySubPojo.class) 行,我获得了NullPointerException。有没有办法管理这种映射?

【问题讨论】:

    标签: hibernate jpa spring-data-jpa nativequery


    【解决方案1】:

    您需要使用@TypeDef 和POJO implementsUserType - POJO 作为自定义类型https://www.baeldung.com/hibernate-custom-types

    点赞class MySubPojo implements UserType

    【讨论】:

    • 如果我理解正确,@TypeDef 注释用于将实体属性转换为特定类型(如链接示例中的 PhoneNumberType)。在这里,我的问题如下:我有一个返回 POJO 的 sql 查询,其中包含子 POJO。我需要在@SqlResultSetMapping 或类似的地方调用 POJO 的类。
    • 部分正确。 @TypeDef 也用于自定义类型以将数据库列映射到复杂的 Java 类型。你可以实现UserType 来做到这一点。
    【解决方案2】:

    除了使用UserType 方法之外,您无法真正做到这一点,但在 Hibernate 6.0 中以这种形式消失了,并且对于这个特定的用例来说使用起来确实很麻烦。我建议您将列单独映射到基本类型的构造函数参数,并在构造函数中构造您需要的任何类型。

    如果您可以避免使用本机查询,您可以使用Blaze-Persistence Entity Views,我认为这里非常适合您的需求。

    我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

    使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

    @EntityView(Entity1.class)
    public interface ResultPojo {
        @IdMapping
        Long getId();
        Integer getFirstSimpleAttribute();
        Integer getSecondSimpleAttribute();
        Double getThirdSimpleAttribute();
        @Mapping("myAssociation")
        MyPojo getMyPojo();
    
        @EntityView(Entity2.class)
        interface MyPojo {
            @IdMapping
            Long getId();
            String getLabel();
            @Mapping("subAssociation")
            MySubPojo getMySubPojo();
        }
        @EntityView(Entity3.class)
        interface MySubPojo {
            String getName();
        }
    }
    

    假设一个实体模型类似如下:

    @Entity
    public class Entity1 {
        @Id
        Long id;
        Integer firstSimpleAttribute;
        Integer secondSimpleAttribute;
        Double thirdSimpleAttribute;
        @ManyToOne(fetch = LAZY)
        Entity2 myAssociation;
    }
    @Entity
    public class Entity2 {
        @Id
        Long id;
        String label;
        @ManyToOne(fetch = LAZY)
        Entity3 subAssociation;
    }
    @Entity
    public class Entity3 {
        @Id
        Long id;
        String label;
    }
    

    查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

    ResultPojo a = entityViewManager.find(entityManager, ResultPojo.class, id);

    Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

    Page<ResultPojo> findAll(Pageable pageable);
    

    最好的部分是,它只会获取实际需要的状态!

    【讨论】:

      猜你喜欢
      • 2018-10-06
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 2021-09-22
      • 2020-06-26
      • 2013-03-16
      • 2014-01-12
      • 1970-01-01
      相关资源
      最近更新 更多