Ankit Katiyar
Ankit Katiyar

Reputation: 3001

HIbernate query cache is caching results as null

I am using ehcache for hibernate second level cahe. Using query cache my query is results are not being cached properly. When second time cahe hits it gives only null at place of object.

Here is my all config.

cfg

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory name="xml-config">
        <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.default_schema">test</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>

        <property name="hibernate.cahe.user_second_level_cache">true</property>
        <property name="hibernate.cache.region.factory_class"> org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        <property name="hibernate.cache.use_query_cache">true</property>

        <property name="hibernate.generate_statistics">true</property>

        <!-- <mapping file="src/main/resources/Owner.hbm.xml" />
        <mapping file="src/main/resources/RentalCar.hbm.xml" /> -->

        <mapping class="com.annon.domain.RentalCar" />
        <mapping class="com.annon.domain.Owner" />
    </session-factory>
</hibernate-configuration>

POJO

    package com.annon.domain;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

/**
 * @author ipg
 * 
 */
@Entity
@Table(name = "anon_owner")
@Cacheable(value = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region="yourEntityCache")
public class Owner {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer ownerId;
    private String name;

    @ManyToMany(targetEntity = RentalCar.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "annon_car_owner", joinColumns = { @JoinColumn(nullable = false, name = "ownerId") }, inverseJoinColumns = { @JoinColumn(nullable = false, name = "carId") })
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region="yourCollectionRegion")
    private List<RentalCar> cars = new ArrayList<RentalCar>();

    public Integer getOwnerId() {
        return ownerId;
    }

    public void setOwnerId(Integer ownerId) {
        this.ownerId = ownerId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<RentalCar> getCars() {
        return cars;
    }

    public void setCars(List<RentalCar> cars) {
        this.cars = cars;
    }

    @Override
    public String toString() {
        return "Owner [ownerId=" + ownerId + ", name=" + name + "]";
    }

}



package com.annon.domain;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.QueryHint;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "annon_rental_car")
@Cacheable(value = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region="yourEntityCache")
@NamedQueries(value = { @NamedQuery(name = "GetOwners", query = "select r.owners from RentalCar r where  r.carId=?", hints = { @QueryHint(name = "org.hibernate.cacheable", value = "true") }) })
@NamedNativeQueries(value = { @NamedNativeQuery(name = "GetOwnersByNative", query = "SELECT DISTINCT ownerId as ownerId,name as name FROM anon_owner ao JOIN annon_car_owner aco WHERE aco.cars_carId=?", hints = { @QueryHint(name = "org.hibernate.cacheable", value = "true") }) })
public class RentalCar {

    @Override
    public String toString() {
        return "RentalCar [carId=" + carId + ", carName=" + carName + "]";
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer carId;

    private String carName;

    @ManyToMany(mappedBy = "cars", fetch = FetchType.EAGER, cascade = CascadeType.ALL, targetEntity = Owner.class)
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region="yourCollectionRegion")
    private List<Owner> owners = new ArrayList<Owner>();

    public Integer getCarId() {
        return carId;
    }

    public void setCarId(Integer carId) {
        this.carId = carId;
    }

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }

    public List<Owner> getOwners() {
        return owners;
    }

    public void setOwners(List<Owner> owners) {
        this.owners = owners;
    }

}

My Test Code

private static void testFetchWithNamedQuery() throws InterruptedException {
        System.out.println("ManyToManyAnnonTest.testFetchWithNamedQuery()");

        showCacheStatus();

        Session session = factory.openSession();
        Query query = session.getNamedQuery("GetOwners");
        query.setParameter(0, 1);
        System.out.println("List-" + query.list());
        System.out.println("Cache Region-" + query.getCacheRegion());
        System.out.println("contains-" + session.contains(query.list().get(0)));
        session.close();

        showCacheStatus();

        Thread.sleep(300);
        System.err.println("%%%%%%%%%%%%%%%%%% second phase start %%%%%%%%%%%%%%%%%%%%%%%");

        session = factory.openSession();
        query = session.getNamedQuery("GetOwners");
        query.setParameter(0, 1);

        System.out.println("List-" + query.list());
        System.out.println("Cache Region-" + query.getCacheRegion());
        showCacheStatus();
        session.close();
    }

    private static void showCacheStatus() {
        System.out.println("%%%%%%%%%%%%% DETAILS OF CACHE %%%%%%%%%%%%%%%");
        org.hibernate.Cache cache = factory.getCache();
        // net.sf.ehcache.CacheManager
        // cacheManager=net.sf.ehcache.CacheManager.getInstance();
        System.out.println("Query cache hit count-" + factory.getStatistics().getQueryCacheHitCount());
        System.out.println("Query cache miss count-" + factory.getStatistics().getQueryCacheMissCount());
        System.out.println("Query cache put count-" + factory.getStatistics().getQueryCachePutCount());
        System.out.println("Query cache execution count-" + factory.getStatistics().getQueryExecutionCount());
        System.out.println("factory.getStatistics().getCollectionLoadCount()--" + factory.getStatistics().getCollectionLoadCount());
        System.out.println("factory.getStatistics().getCollectionFetchCount()--" + factory.getStatistics().getCollectionFetchCount());
        System.out.println("Contains Owner 1-" + cache.containsEntity(Owner.class, 1));
        System.out.println("Contains Car 1-" + cache.containsEntity(RentalCar.class, 1));

    }

OUTPUT

%%%%%%%%%%%%% DETAILS OF CACHE %%%%%%%%%%%%%%%
Query cache hit count-0
Query cache miss count-0
Query cache put count-0
Query cache execution count-0
factory.getStatistics().getCollectionLoadCount()--0
factory.getStatistics().getCollectionFetchCount()--0
Contains Owner 1-false
Contains Car 1-false
Hibernate: select owner2_.ownerId as ownerId1_2_, owner2_.name as name2_2_ from test.annon_rental_car rentalcar0_ inner join test.annon_car_owner owners1_ on rentalcar0_.carId=owners1_.carId inner join test.anon_owner owner2_ on owners1_.ownerId=owner2_.ownerId where rentalcar0_.carId=?
Hibernate: select cars0_.ownerId as ownerId1_2_0_, cars0_.carId as carId2_0_0_, rentalcar1_.carId as carId1_1_1_, rentalcar1_.carName as carName2_1_1_ from test.annon_car_owner cars0_ inner join test.annon_rental_car rentalcar1_ on cars0_.carId=rentalcar1_.carId where cars0_.ownerId=?
Hibernate: select owners0_.carId as carId2_1_0_, owners0_.ownerId as ownerId1_0_0_, owner1_.ownerId as ownerId1_2_1_, owner1_.name as name2_2_1_ from test.annon_car_owner owners0_ inner join test.anon_owner owner1_ on owners0_.ownerId=owner1_.ownerId where owners0_.carId=?
Hibernate: select owners0_.carId as carId2_1_0_, owners0_.ownerId as ownerId1_0_0_, owner1_.ownerId as ownerId1_2_1_, owner1_.name as name2_2_1_ from test.annon_car_owner owners0_ inner join test.anon_owner owner1_ on owners0_.ownerId=owner1_.ownerId where owners0_.carId=?
**List-[Owner [ownerId=1, name=Owner]]**
Cache Region-null
contains-false
%%%%%%%%%%%%% DETAILS OF CACHE %%%%%%%%%%%%%%%
Query cache hit count-1
Query cache miss count-1
Query cache put count-1
Query cache execution count-1
factory.getStatistics().getCollectionLoadCount()--3
factory.getStatistics().getCollectionFetchCount()--3
Contains Owner 1-true
Contains Car 1-true
%%%%%%%%%%%%%%%%%% second phase start %%%%%%%%%%%%%%%%%%%%%%%
**List-[null]**
Cache Region-null
%%%%%%%%%%%%% DETAILS OF CACHE %%%%%%%%%%%%%%%
Query cache hit count-2
Query cache miss count-1
Query cache put count-1
Query cache execution count-1
factory.getStatistics().getCollectionLoadCount()--3
factory.getStatistics().getCollectionFetchCount()--3
Contains Owner 1-true
Contains Car 1-true

I am working on this from long time but no result yet.

Upvotes: 2

Views: 1100

Answers (1)

Ankit Katiyar
Ankit Katiyar

Reputation: 3001

I fixed it by changing HQL

Old HQL

select r.owners from RentalCar r where  r.carId=?

Fixed HQL

select o from RentalCar c join c.owners o where c.carId=?

Upvotes: 2

Related Questions