[hibernate-issues] [Hibernate-JIRA] Updated: (HHH-3930) one-to-one causes redundant select query

Strong Liu (JIRA) noreply at atlassian.com
Wed Oct 19 13:52:19 EDT 2011


     [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-3930?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Strong Liu updated HHH-3930:
----------------------------

    Description: 
{code}
@Entity
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(mappedBy = "address")
    private Customer customer;
}

@Entity
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Address address = new Address();

    public Long getId() {
	return id;
    }

    public Address getAddress() {
	return address;
    }
}
{code}
This mapping causes 2 instead of the expected 1 query to retrieve a Customer and its Address from the db:

select * from Customer customer0_ left outer join Address address1_ on customer0_.address_id=address1_.id where customer0_.id=?
select * from Customer customer0_ left outer join Address address1_ on customer0_.address_id=address1_.id where customer0_.address_id=?

Changing the mapping to a LAZY fetch type:

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Address address = new Address();

Causes 3 select queries instead of the expected 2 queries to retrieve a Customer (and its Address) from the db:

select * from Customer customer0_ where customer0_.id=?
select * from Address address0_ left outer join Customer customer1_ on address0_.id=customer1_.address_id where address0_.id=?
select * from Customer customer0_ where customer0_.address_id=?

The third select is superfluous because the relationship is already completely known: you already have the customer, so why not just set it on the address entity?

Making the address field in Customer a @ManyToOne doesn't make a difference.

Making the customer field in Address a @OneToMany does remove the extra select, but forces our model to change the relationship from Customer to List<Customer> where we *know* there'll be only 1 element.

Apparently Hibernate can figure out the reverse relationship with a @ManyToOne - @OneToMany without the need for additional queries, can't this be extended to @OneToOne bidirectional relationships as well?


  was:
@Entity
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(mappedBy = "address")
    private Customer customer;
}

@Entity
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Address address = new Address();

    public Long getId() {
	return id;
    }

    public Address getAddress() {
	return address;
    }
}

This mapping causes 2 instead of the expected 1 query to retrieve a Customer and its Address from the db:

select * from Customer customer0_ left outer join Address address1_ on customer0_.address_id=address1_.id where customer0_.id=?
select * from Customer customer0_ left outer join Address address1_ on customer0_.address_id=address1_.id where customer0_.address_id=?

Changing the mapping to a LAZY fetch type:

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Address address = new Address();

Causes 3 select queries instead of the expected 2 queries to retrieve a Customer (and its Address) from the db:

select * from Customer customer0_ where customer0_.id=?
select * from Address address0_ left outer join Customer customer1_ on address0_.id=customer1_.address_id where address0_.id=?
select * from Customer customer0_ where customer0_.address_id=?

The third select is superfluous because the relationship is already completely known: you already have the customer, so why not just set it on the address entity?

Making the address field in Customer a @ManyToOne doesn't make a difference.

Making the customer field in Address a @OneToMany does remove the extra select, but forces our model to change the relationship from Customer to List<Customer> where we *know* there'll be only 1 element.

Apparently Hibernate can figure out the reverse relationship with a @ManyToOne - @OneToMany without the need for additional queries, can't this be extended to @OneToOne bidirectional relationships as well?



> one-to-one causes redundant select query
> ----------------------------------------
>
>                 Key: HHH-3930
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3930
>             Project: Hibernate Core
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.3.1
>            Reporter: Martijn Dashorst
>
> {code}
> @Entity
> public class Address {
>     @Id
>     @GeneratedValue(strategy = GenerationType.AUTO)
>     private Long id;
>     @OneToOne(mappedBy = "address")
>     private Customer customer;
> }
> @Entity
> public class Customer {
>     @Id
>     @GeneratedValue(strategy = GenerationType.AUTO)
>     private Long id;
>     @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
>     private Address address = new Address();
>     public Long getId() {
> 	return id;
>     }
>     public Address getAddress() {
> 	return address;
>     }
> }
> {code}
> This mapping causes 2 instead of the expected 1 query to retrieve a Customer and its Address from the db:
> select * from Customer customer0_ left outer join Address address1_ on customer0_.address_id=address1_.id where customer0_.id=?
> select * from Customer customer0_ left outer join Address address1_ on customer0_.address_id=address1_.id where customer0_.address_id=?
> Changing the mapping to a LAZY fetch type:
> @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
> private Address address = new Address();
> Causes 3 select queries instead of the expected 2 queries to retrieve a Customer (and its Address) from the db:
> select * from Customer customer0_ where customer0_.id=?
> select * from Address address0_ left outer join Customer customer1_ on address0_.id=customer1_.address_id where address0_.id=?
> select * from Customer customer0_ where customer0_.address_id=?
> The third select is superfluous because the relationship is already completely known: you already have the customer, so why not just set it on the address entity?
> Making the address field in Customer a @ManyToOne doesn't make a difference.
> Making the customer field in Address a @OneToMany does remove the extra select, but forces our model to change the relationship from Customer to List<Customer> where we *know* there'll be only 1 element.
> Apparently Hibernate can figure out the reverse relationship with a @ManyToOne - @OneToMany without the need for additional queries, can't this be extended to @OneToOne bidirectional relationships as well?

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list