Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent Hibernate fetching joined entities when I access only the foreign key id?

I have a Hibernate entity Parent that is joined to another: Child. In the database I have a column parent.child_id that has a foreign key constraint on child.id. Assuming I'm lazily loading, when I load an instance of Parent I expect to be able to access parent.getChild().getId() without incurring a lookup on the child table.

I expected the proxy returned by parent.getChild() to be able to fulfil a request to Child.getId() as it has already loaded the child's id from parent.child_id column. However, I see an additional query on the child table.

Why is this extra query necessary, and how can I avoid it? In this instance I'm only interested in the foreign key ID, and do not wish to load the whole row.

Classes:

class Parent {
  @Id @Column(name = "id", unique = true, nullable = false)
  private Integer id;

  @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "child_id")
  private Child child;
}

class Child {
  @Id @Column(name = "id", unique = true, nullable = false)
  private Integer id;

  @Column(name = "name")
  private String name;
}

Tables:

CREATE TABLE child (
    id int PRIMARY KEY,
    name varchar(10)
);

CREATE TABLE parent (
    id int PRIMARY KEY,
    child_id int REFERENCES (child.id)
);
like image 590
teabot Avatar asked Mar 18 '11 12:03

teabot


People also ask

How do you make a foreign key a primary key in Hibernate?

Use @PrimaryKeyJoinColumn and @PrimaryKeyJoinColumns annotations. From Hibernate manual: The @PrimaryKeyJoinColumn annotation does say that the primary key of the entity is used as the foreign key value to the associated entity.

What is foreign key in Hibernate?

Introduction. In this post, we feature a comprehensive Example on Hibernate Foreign Key. Foreign key refers to single column or group of columns in table that link data present in another table through its primary key. A Foreign key can't exist without its parent key but viceversa is not true.

What is entity Hibernate?

Hibernate will scan that package for any Java objects annotated with the @Entity annotation. If it finds any, then it will begin the process of looking through that particular Java object to recreate it as a table in your database! Before Hibernate will start it's scan, not only do we need to invoke the sessionFactory.


1 Answers

It's caused by the fact that Child uses field access (since annotations are placed on fields), therefore Hibernate simply initializes the proxy when you call any of its methods.

If you move annotations to properies, it would work as expected.

Since JPA 2.0 (Hibernate 3.5) you can configure it in fine-grained way:

@Access(AccessType.FIELD) // Default is field access
class Child {
    private Integer id;

    @Column(name = "name")
    private String name;

    @Access(AccessType.PROPERTY) // Use property access for id
    @Id @Column(name = "id", unique = true, nullable = false)
    public Integer getId() { ... }

    ...   
}
like image 152
axtavt Avatar answered Oct 15 '22 09:10

axtavt