当前位置: 首页 > 知识库问答 >
问题:

Spring JPA:在join with annotation/JPQL上选择特定列

谭繁
2023-03-14

我正在努力熟悉spring和jpa。首先,有一个包含动画细节的表格anime_details。由于db可以有许多类型,所以它有另一个名为genre的表。包含多对多关系项的中间表也存在。当我通过id查询任何动画时,它应该返回动画的详细信息以及类型。

它确实返回一个对象,其中包含动画的详细信息和类型对象列表(如预期的那样)。但我想要的是限制将从类型对象中获取的列。例如只有id或只有id和name(以防有比这些更多的列)。

动物尾巴

@Getter
@Setter
@Entity
@Table(name = "anime_details")
public class AnimeDetails {
    @Id
    @SequenceGenerator(name = "animeDetailsSeq", sequenceName =
        "anime_details_id_seq",
        allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
        "animeDetailsSeq")
    private Integer id;

    private String name;
    private Integer episodes;
    private Date started;
    private Date ended;
    private String status;

    @ManyToMany
    @JoinTable(
        name = "anime_genre",
        joinColumns = @JoinColumn(name = "details_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "genre_id", referencedColumnName = "id"))
    @JsonManagedReference
    private List<Genre> genres;

    protected AnimeDetails() {
    }
}

体裁

@Data
@Entity
@Table(name = "genre")
public class Genre {
    @Id
    @SequenceGenerator(name = "genreSeq", sequenceName = "genre_id_seq",
        allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "genreSeq")
    private Integer id;
    private String name;

    @ManyToMany(mappedBy = "genres")
    List<AnimeDetails> animes;

    protected Genre() {

    }
}

预期有效载荷

 {
    "id": 2,
    "name": "Your Name",
    "episodes": 1,
    "started": "2016-08-25T18:00:00.000+0000",
    "ended": "2016-08-25T18:00:00.000+0000",
    "status": "Completed",
    "genres": [
        {
            "id": 5,
            "name": "Drama"
        },
        {
            "id": 10,
            "name": "Supernatural"
        }
    ]
}

现在,我得到结果并逐个手动获取列并将它们设置在DTO中。但这并不高效,因为数据库查询已经获取了比需要的更多的数据。是否有任何特定的注释/属性/jpql来减少它?

共有2个答案

范俊逸
2023-03-14

今天我尝试了一个不同的解决方案。让我们先看看代码。

体裁

@Data
@Entity
@Table(name = "genre")
public class Genre {
    @Id
    @SequenceGenerator(name = "genreSeq", sequenceName = "genre_id_seq",
        allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "genreSeq")
    private Integer id;
    private String name;

    @ManyToMany
    @JoinTable(
        name = "anime_genre",
        joinColumns = @JoinColumn(name = "genre_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "details_id", referencedColumnName = "id"))
    List<AnimeIdentity> animes;

    protected Genre() {

    }
}

动画识别

@Getter
@Setter
@Entity
@Table(name = "anime_details")
public class AnimeIdentity {
    @Id
    @SequenceGenerator(name = "animeDetailsSeq", sequenceName =
        "anime_details_id_seq",
        allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
        "animeDetailsSeq")
    private Integer id;

    private String name;

    protected AnimeIdentity() {};
}

Hibernate提出的问题

Hibernate: select genre0_.id as id1_2_0_, genre0_.name as name2_2_0_ from genre genre0_ where genre0_.id=?<br>
Hibernate: select animes0_.genre_id as genre_id2_1_0_, animes0_.details_id as details_1_1_0_, animeident1_.id as id1_0_1_, animeident1_.name as name2_0_1_ from anime_genre animes0_ inner join anime_details animeident1_ on animes0_.details_id=animeident1_.id where animes0_.genre_id=?

请随意告诉我这个解决方案的优缺点。对我来说,如果我的需求仅限于此,这是一个很好的解决方案。但是,在不同类型的查询中,生成越来越多的实体POJO将是一项烦人的任务。

惠翰藻
2023-03-14

确实,我们正在寻找一个关于同一问题的适当解决方案,因为正如您所指出的,它正在造成性能问题,因为应用程序和数据库之间存在大量无用的数据负载。想象一下,不仅有一个查询,还有更多查询,你需要一个全局优化解决方案。。。

>

  • 从一开始Spring DATA不支持此操作,因此它会引导您进行手动配置并在DTO引用上进行设置。如果您使用自定义对象并使用构造函数在JPQL中返回该对象,或者编写本机查询,则同样适用

    另一件事是,当您在下面使用hibernate时,它提供了自定义映射程序,您可以随时编写自定义HQL(而不是jpql),设置适当的DAO,连接EntityManager或直接连接SessionFactory(这打破了抽象的JPA合同,但您可以利用hibernates提供的全部好处),然后返回相同的对象,但只有你需要的专栏。

    第二点的例子:

    import javax.persistence.EntityManager;
    import org.hibernate.query.Query;
    import org.hibernate.transform.Transformers;
    
    public CustomEntity getEntity(){
            Query<CustomEntity> q = (Query<CustomEntity>) entityManager.createQuery("select 
                             e.id,e.name from CustomEntity e where e.name = 'parameter'");
            q.setResultTransformer(Transformers.aliasToBean(CustomEntity.class));
            CustomEntity entity = (CustomEntity) q.getSingleResult();
            return name;
        }
    

    注意CustomEntity是数据库中的托管实体Bean/Table,只是将此示例放置在您可能需要实现的内容附近。

    试过

    • Spring boot 2.0.5。发布
    • Spring数据2.0.5。发布
    • Hibernate core 5.2.17。最终

  •  类似资料:
    • 问题内容: 我在两个实体之间有一个多对多关系:汽车和经销商。 在本机MySQL中,我有: 我想在JPQL中进行的查询是: 使JPQL等效的正确方法是什么? 我的Java方法签名是: 我努力了 这是我在Java中这种关系的JPA注释: 编辑 我也尝试过: 哪个抛出错误: 问题答案: 该参数必须是Dealership实例的集合。 如果要使用经销商ID的集合,请使用 请记住,JPQL始终使用实体,映射的

    • 我是一个新生的QA,我在这里尝试编写一个Protractor脚本,从下拉列表中选择一个选项。我的下拉列表中有两个选项,我正在尝试从数字中选择它。 这是我正在使用的代码。 默认情况下,选项 2 在页面加载时处于选中状态。我需要的是从下拉列表中选择选项1。但是,我的代码不会这样做。 下面是选择选项的代码片段。 提前感谢:)

    • 问题内容: 我正在使用Spring JPA执行所有数据库操作。但是我不知道如何从Spring JPA的表中选择特定的列? 例如: 问题答案: 你可以从这样的类中在注释中进行设置: 请注意,你将不得不自己进行映射。像这样使用常规映射查找可能会更容易,除非你确实只需要这两个值: 也许也值得看一下Spring数据文档。

    • 我正在使用Spring JPA执行所有数据库操作。但是,我不知道如何在Spring JPA中从表中选择特定的列? 例如:

    • 我想显示“users”表中两个指定列“first_name”和“pic”的所有值。我正在尝试“Pulk”,但它在echo时显示为json格式。但我需要展示给大家看,一些东西——‘John pic’。求求你,有人帮帮我。这是我在“索引”中的示例代码。刀身php的吼声-

    • 我将html写成 现在我希望如果选项是1,那么它应该被选择为 请帮帮我!!!