Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用hibernate查询仅获取具有关联的实体的某些字段?_Java_Hibernate - Fatal编程技术网

Java 如何使用hibernate查询仅获取具有关联的实体的某些字段?

Java 如何使用hibernate查询仅获取具有关联的实体的某些字段?,java,hibernate,Java,Hibernate,我有一个实体,它有多个字段,其中一些是关联。 假设该实体具有与以下类似的结构: @Entity @Table(name="foos") public class Foo { public Foo() {} @Id private Long id; @Column private String name; @OneToOne(fetch = FetchType.EAGER) @JoinColumn(name = "bar_id") private Bar ba

我有一个实体,它有多个字段,其中一些是关联。 假设该实体具有与以下类似的结构:

@Entity
@Table(name="foos")
public class Foo {

  public Foo() {}
  @Id
  private Long id;

  @Column
  private String name;

  @OneToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "bar_id")
  private Bar bar;

  @ManyToOne
  @JoinColumn(name = "bar1_id")
  private Bar1 bar1;

  @ManyToOne
  @JoinColumn(name = "bar2_id")
  private Bar2 bar2;

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
  @JoinColumn(name = "foo_id")
  private List<Bar3> bar3;

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
  @JoinColumn(name = "foo_id")
  private List<Bar4> bar4;

  //getters and setters
}
@实体
@表(name=“foos”)
公开课Foo{
公共Foo(){}
@身份证
私人长id;
@纵队
私有字符串名称;
@OneToOne(fetch=FetchType.EAGER)
@JoinColumn(name=“bar\u id”)
私人酒吧;
@许多酮
@JoinColumn(name=“bar1\u id”)
私人酒吧1酒吧1;
@许多酮
@JoinColumn(name=“bar2\u id”)
私人酒吧2酒吧2;
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,orphan=true)
@JoinColumn(name=“foo\u id”)
私人名单3;
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,orphan=true)
@JoinColumn(name=“foo\u id”)
私人名单4;
//接球手和接球手
}
我的问题是如何使用Hibernate查询仅加载一些字段而不是整个实体?
我只想获取id、bar、bar1和bar3,不想获取创建的Foo对象中的其余字段(名称、bar2、bar4)。

我对Hibernate非常陌生,因此任何建议都将受到欢迎。

最简单的方法是创建一个存储库,根据选择的标准获取对象,然后如果使用Spring数据,则仅从对象列表中提取所需的字段:

仅对于hibernate,它应该如下所示:

    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    Foo foo = entityManager.find(Foo.class,id);

    entityManager.getTransaction().commit();
或使用自定义SQL查询,仅适用于所选字段:

    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    Query query = entityManager.createQuery("SELECT e FROM Foo e");
    List<Foo> workerList = query.getResultList();
EntityManager EntityManager=EntityManager工厂。createEntityManager();
entityManager.getTransaction().begin();
Query Query=entityManager.createQuery(“从fooE中选择e”);
List workerList=query.getResultList();

在以下帮助下,我解决了这个问题。我创建了一个新的实体FooShort,具有相同的表名“foos”,并且只包含Foo所需的字段

@Entity
@Table(name="foos")
public class FooShort {

  public FooShort() {}
  @Id
  private Long id;

  @OneToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "bar_id")
  private Bar bar;

  @ManyToOne
  @JoinColumn(name = "bar1_id")
  private Bar1 bar1;

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
  @JoinColumn(name = "foo_id")
  private List<Bar3> bar3;

  //getters and setters
}
@实体
@表(name=“foos”)
公开课{
公共FooShort(){}
@身份证
私人长id;
@OneToOne(fetch=FetchType.EAGER)
@JoinColumn(name=“bar\u id”)
私人酒吧;
@许多酮
@JoinColumn(name=“bar1\u id”)
私人酒吧1酒吧1;
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER,orphan=true)
@JoinColumn(name=“foo\u id”)
私人名单3;
//接球手和接球手
}
Hibernate 5,Spring 5

您有几个选项,但最简单的选项是使用所需的列/字段创建一个简单的@Query,请参见我的一个项目中的示例代码

首先也是最重要的一点是,您不需要创建带有子集字段的DTO,我将显示这两个字段和混合版本的选项

选项一:带有列/字段子集的DTO对象

DTO存储库代码:

@Query( "SELECT new com.your.package.name.customers.CompanyDTOIdName(c.id, c.name) " +
        "FROM Company c " +
        "WHERE c.enabled = 1 " +
        "ORDER BY c.name ASC"           )
List<CompanyDTOIdName> compDtoNameWhereEnabledTrue();
@Query( "SELECT new com.your.package.name.customers.Company(c.id, c.name) " +
        "FROM Company c " +
        "WHERE c.enabled = 1 " +
        "ORDER BY c.name ASC"
)
List<Company> compNameWhereEnabledTrue();
@Query( "SELECT new com.csfactorynw2.site.customers.Company(c.id, c.name) " +
            "FROM Company c " +
            "WHERE c.enabled = 1 " +
            "ORDER BY c.name ASC"
    )
    List<CompanyDTOIdNameInterface> compNameWhereEnabledTrue();
休眠SQL执行代码:

SELECT
    new com.your.package.name.customers.CompanyDTOIdName(c.id, c.name) 
FROM
    Company c 
WHERE
    c.enabled = 1 
ORDER BY
    c.name ASC

select
    company0_.companyId as col_0_0_,
    company0_.name as col_1_0_ 
from
    ome_company company0_ 
where
    company0_.enabled=1 
order by
    company0_.name ASC
SELECT
    new com.your.package.name.customers.Company(c.id, c.name) 
FROM
    Company c 
WHERE
    c.enabled = 1 
ORDER BY
    c.name ASC

select
    company0_.companyId as col_0_0_,
    company0_.name as col_1_0_ 
from
    ome_company company0_ 
where
    company0_.enabled=1 
order by
    company0_.name ASC
主要的缺点是,对于每一个不同的列组合,都需要一个单独的DTO对象


选项二:使用原始@Entity

第二个选项更简单,可用于任何列子集,如下所示:

存储库代码:

@Query( "SELECT new com.your.package.name.customers.CompanyDTOIdName(c.id, c.name) " +
        "FROM Company c " +
        "WHERE c.enabled = 1 " +
        "ORDER BY c.name ASC"           )
List<CompanyDTOIdName> compDtoNameWhereEnabledTrue();
@Query( "SELECT new com.your.package.name.customers.Company(c.id, c.name) " +
        "FROM Company c " +
        "WHERE c.enabled = 1 " +
        "ORDER BY c.name ASC"
)
List<Company> compNameWhereEnabledTrue();
@Query( "SELECT new com.csfactorynw2.site.customers.Company(c.id, c.name) " +
            "FROM Company c " +
            "WHERE c.enabled = 1 " +
            "ORDER BY c.name ASC"
    )
    List<CompanyDTOIdNameInterface> compNameWhereEnabledTrue();
休眠SQL执行代码:

SELECT
    new com.your.package.name.customers.CompanyDTOIdName(c.id, c.name) 
FROM
    Company c 
WHERE
    c.enabled = 1 
ORDER BY
    c.name ASC

select
    company0_.companyId as col_0_0_,
    company0_.name as col_1_0_ 
from
    ome_company company0_ 
where
    company0_.enabled=1 
order by
    company0_.name ASC
SELECT
    new com.your.package.name.customers.Company(c.id, c.name) 
FROM
    Company c 
WHERE
    c.enabled = 1 
ORDER BY
    c.name ASC

select
    company0_.companyId as col_0_0_,
    company0_.name as col_1_0_ 
from
    ome_company company0_ 
where
    company0_.enabled=1 
order by
    company0_.name ASC
注意:我相信您可以看到这种方法的问题。仅加载指定的列/字段。如果试图访问未启动的字段,则会出现异常


使用接口的混合版本(两个世界中最好的)

使用必需的访问器字段创建接口

public interface CompanyDTOIdNameInterface {

    public Long getId();
    public String getName();
}
在@Entity对象上实现接口

public class Company implements Serializable,
                                CompanyDTOIdNameInterface
{ /* omitted code */ }
存储库代码:

@Query( "SELECT new com.your.package.name.customers.CompanyDTOIdName(c.id, c.name) " +
        "FROM Company c " +
        "WHERE c.enabled = 1 " +
        "ORDER BY c.name ASC"           )
List<CompanyDTOIdName> compDtoNameWhereEnabledTrue();
@Query( "SELECT new com.your.package.name.customers.Company(c.id, c.name) " +
        "FROM Company c " +
        "WHERE c.enabled = 1 " +
        "ORDER BY c.name ASC"
)
List<Company> compNameWhereEnabledTrue();
@Query( "SELECT new com.csfactorynw2.site.customers.Company(c.id, c.name) " +
            "FROM Company c " +
            "WHERE c.enabled = 1 " +
            "ORDER BY c.name ASC"
    )
    List<CompanyDTOIdNameInterface> compNameWhereEnabledTrue();
@Query(“选择新com.csfactorynw2.site.customers.Company(c.id,c.name)”+
“来自c公司”+
“其中c.enabled=1”+
“按c.name ASC订购”
)
列出compNameWhereEnabledTrue();

就这么简单。祝你好运:)

谢谢你的回答。但我认为上面的查询将从数据库中获取foo对象的所有字段。我想要的是只从db将上述四个字段加载到foo对象中,即,生成的foo对象不应从db中获取bar2和bar4的任何值。修改HQL查询应该可以做到这一点,即“从FooE中选择e.name”。如果您需要HQL方面的帮助,这里有一个教程。如果您愿意,Hibernate还允许使用本机SQL查询。我试过了,对于作为表一部分的列,这将很好地工作。但是对于关联,必须编写大量连接,这可能会使查询变得复杂。在林克的帮助下,我解决了这个问题。我创建了一个新的实体FooShort,具有相同的表名“foos”,并且只包含Foo所需的字段。