2014-12-26 49 views
6

简单的例子:休眠,获得国外ID,而无需加载相关实体

映射:

@Entity 
public class City { 
    @[email protected] 
    private Integer id; 

    private String name; 

    @ManyToOne(fetch = FetchType.LAZY) 
    private Country country; 
... 


@Entity 
public class Country { 
    @[email protected] 
    private Integer id; 

    private String name; 
... 

用法:

Query query = session.createQuery("from City"); 
List<?> cities = query.list(); 
for (Object cityObj : cities) { 
    City city = (City) cityObj; 
    System.out.printf("City: %s %s%n", city.getId(), city.getName()); 
    Country country = city.getCountry(); 
    System.out.println("Country retrieved"); 
    Integer countryId = country.getId(); 
    System.out.printf("Country id: %s%n", countryId); 
} 

这里的输出:

Hibernate: select city0_.id as id0_, city0_.country_id as country3_0_, city0_.name as name0_ from City city0_ 
City: 1 Astana 
Country retrieved 
Hibernate: select country0_.id as id1_0_, country0_.name as name1_0_ from Country country0_ where country0_.id=? 
Country id: 1 
City: 2 Almaty 
Country retrieved 
Country id: 1 
City: 3 Omsk 
Country retrieved 
Hibernate: select country0_.id as id1_0_, country0_.name as name1_0_ from Country country0_ where country0_.id=? 
Country id: 2 

现在,这是一个奇怪的行为。我可以得到Country对象(可能是一些代理),而Hibernate没有发出任何额外的SQL查询。但是当我调用country.getId() - hibernate发出SQL查询来加载完整的国家对象。很显然,Hibernate知道country.id的值,所以我期望hibernate只会在没有任何额外的SQL查询的情况下返回这个id。但事实并非如此。

问题是 - 我不需要整个实体。我只需要id,我不想要单独的SQL查询(或者如果我设置FetchType.EAGER,则为JOIN查询)。

+0

也许这是Hibernate映射是如何工作的获取所有子在查询只有一个实体时记录实体 –

回答

6

我想你将不得不改变你的Country实体,如下所示。在Id字段中添加AccessType注释。

@Entity 
    public class Country { 
     @[email protected]@AccessType("property") 
     private Integer id; 

     private String name; 

面对类似的问题,并遵循这篇文章: - Accessor Type Annotation

+0

谢谢。我调试了hibernate代码,发现如果我在getId方法而不是id属性上设置@Id注解,它也可以工作。奇怪的行为,但这可能是休眠的工作原理。 – vbezhenar

+0

注意:使用@AccessType时,还需要一个id公共setter,否则尝试加载实体时会遇到大量异常。 –

+0

@AlexandruSeverin我用这个没有setter,它工作正常:)也许它已被固定。 – Edd

1

所以正确的JPA的唯一标准的解决方案将是:

@Entity 
public class Country { 

    @Id @GeneratedValue @Access(PROPERTY) 
    private Integer id; 
+0

我不认为Access注释是必要的。 – T3rm1