Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA+Hibernate...Instead of single query, association executes multiple queries for join

I have two class named Banneers and BannerGroup.

I have created bidirectional relationship. In my case, A BannerGroup can have many Banners and Many Banners belongs within a same BannerGroup.

Mysql tables are...

mysql> desc Banners;
+------------------+--------------+------+-----+---------+-----------------------------+
| Field            | Type         | Null | Key | Default | Extra                       |
+------------------+--------------+------+-----+---------+-----------------------------+
| banner_id        | int(11)      | NO   | PRI | NULL    | auto_increment              | 
| banner_name      | varchar(255) | YES  |     | NULL    |                             | 
| banner_group_id  | int(11)      | YES  | MUL | NULL    |                             | 
+------------------+--------------+------+-----+---------+-----------------------------+

mysql> desc Banner_Group;
+---------------------+--------------+------+-----+----------------+-----------------------------+
| Field               | Type         | Null | Key | Default        | Extra                       |
+---------------------+--------------+------+-----+----------------+-----------------------------+
| group_id            | int(11)      | NO   | PRI | NULL           | auto_increment              | 
| group_name          | varchar(255) | NO   | MUL | NULL           |                             | 
+---------------------+--------------+------+-----+----------------+-----------------------------+

My model class is like this...

Class Banners
{
    private Integer bannerId;
    private String bannerName;
    private BannerGroup bannerGroupDO;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "banner_id")
    public Integer getBannerId() {
        return bannerId;
    }

    public void setBannerId(Integer bannerId) {
        this.bannerId = bannerId;
    }

    @Column(name = "banner_name")
    public String getBannerName() {
        return bannerName;
    }

    public void setBannerName(String bannerName) {
        this.bannerName = bannerName;
    }

    @ManyToOne(fetch = FetchType.EAGER, optional=false)
    @JoinColumn(name = "banner_group_id",  nullable = false)
    public BannerGroup getAffiliateBannerGroup() {
        return bannerGroupDO;
    }

    public void setAffiliateBannerGroup(BannerGroup bannerGroupDO) {
        this.bannerGroupDO = bannerGroupDO;
    }
}

Class BannerGroup{

    private int group_id;
    private int group_name;
    private List<Banners> banners;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "group_id")
    public Integer getGroupId() {
        return groupId;
    }

    public void setGroupId(Integer groupId) {
        this.groupId = groupId;
    }

    @Column(name = "group_name")
    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    @OneToMany(mappedBy="bannerGroupDO", fetch = FetchType.LAZY)
    public List<Banners> getBanners() {
        return banners;
    }

    public void setBanners(List<Banners> banners) {
    this.banners = banners;
    }
}

Now, when i am trying to get Banners(which is eagerly loaded BannerGroup)

Query q = session.createQuery("from com.abc.xyz.model.Banners where bannerId = 123");

I got this...

Hibernate: select b.banner_id as banner1_294_, b.banner_name as banner2_294_ from Banners b where b.banner_id=?
Hibernate: select bg.group_id as group1_295_0_, bg.group_name as group9_295_0_ from Banner_Group bg where bg.group_id=?

What i want: Hibernate should execute single query instead of multiple(two) queries. I want that hibernate should fire a "inner join" query... something like...

select b.*, bg.* from Banners b INNER JOIN Banner_Group bg ON b.banner_group_id=bg.group_id;

My questions are...

1.) Why hibernate executes multiple queries instead of single query, eventhough i have specified association. ?

2.) What suould i suppose to do for this problem?

I do not want to execute JPQL/HQL. I mean to say, i want to get behaviour form association only. I just want a result by executing query like... from com.abc.xyz.model.Banners where bannerId = 123;

3.) I know that... Result of executing two queries individually and a single query is same. But i think this affects on perfomance of DB. or may be its a bruden for DB. Am i wrong?

After the answer of Radim Köhler... i have Edited my code in Banners.java ...(still problem is not solved)

@ManyToOne(fetch = FetchType.EAGER, optional=false)
    @JoinColumn(name = "banner_group_id",  nullable = false)
    @Fetch(FetchMode.JOIN)
    public AffiliateBannerGroup getAffiliateBannerGroup() {
        return affiliateBannerGroup;
    }

    public void setAffiliateBannerGroup(AffiliateBannerGroup affiliateBannerGroup) {
        this.affiliateBannerGroup = affiliateBannerGroup;
    }
like image 875
Manan Shah Avatar asked Nov 11 '22 19:11

Manan Shah


1 Answers

The mapping missing is the

@Fetch(FetchMode.JOIN)

see more here: JPA eager fetch does not join.

The EAGER setting, is instructing Hibernate in a different way: Do not wait to load Entity and its Reference. So, even if it is not used in the further processing, the reference is loaded. LAZY loading, is in most scenarios prefered and most appropriate way

like image 133
Radim Köhler Avatar answered Nov 28 '22 07:11

Radim Köhler