2013-03-08 12 views
7

Posiadamy rozbudowany model podmiotu z ponad 100 klasami jednostek. Wszystkie klasy encji są podklasami pojedynczych nadklas. Współdzielony tryb pamięci podręcznej został ustawiony na ALL.Dedykowany region pamięci podręcznej dla podklas jednostki?

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
@Table(name = "entities") 
public abstract class LongIdEntity { 

    @Id 
    @GeneratedValue(strategy = GenerationType.TABLE) 
    private Long id; 

    @Version 
    @Column(name = "OPT_LOCK_VERSION") 
    private Long lockVersion; 

    etc... 

} 

Przykładem podklasy:

@Entity 
@Table(name = "cars") 
public class Car extends LongIdEntity { ... } 

Chcielibyśmy buforować wszystkie podmioty w pamięci podręcznej poziomu 2. Problem polega na tym, że tylko jeden region pamięci podręcznej jest tworzony dla wszystkich podmiotów; o nazwie LongIdEntity.

Debugowanie pokazuje, czy Hibernacja wykonała znajdź wszystkie klasy obiektów, ale mimo to przydzieli je do tego samego regionu. Ponieważ w SessionFactoryImpl: 339:

String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName(); 

W naszym przypadku, wywołanie model.getRootClass() zawsze plastyczności "LongIdEntity".

Przypuszczam, że rzeczywiście przechowywałoby to wszystkie jednostki, ale bez kontroli eksmisji. Niektóre zajęcia są bardzo częste i tylko do odczytu. Dlatego chcemy, aby były przypięte do pamięci. Niektóre są zwykle używane w określonym przedziale czasowym, itd ... Wbijanie wszystkiego do tego samego bufora unieważnia to wszystko.

Określenie regionu w adnotacji nie przynosi efektu. Na przykład:

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,region = "cars") 
@Entity 
@Table(name = "cars") 
public class Car extends LongIdEntity { ... } 

dziwne jest to, że tylko wspólne tryb cache ALL podnosi klasy podmiotu. W żadnym innym trybie żadne podmioty nie są - nawet w przypadku adnotacji przy użyciu @Cache i/lub @Cacheable. Może to jest wskazanie?

Ktoś ma pomysł, w jaki sposób mogę przypisać określone klasy obiektów do określonych regionów?

TIA :-)

persistence.xml jest elementarny:

fabryka
<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="cars" transaction-type="RESOURCE_LOCAL"> 
    <shared-cache-mode>ALL</shared-cache-mode> 
    </persistence-unit> 
</persistence> 

Sesja wykonana jest klasyczny sposób:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/> 
    <property name="persistenceUnitName" value="optimus"/> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="jpaProperties"> 
     <props> 
     <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop> 
     <prop key="hibernate.cache.use_second_level_cache">true</prop> 
     <prop key="hibernate.cache.use_query_cache">true</prop> 
     <prop key="hibernate.generate_statistics">true</prop> 
     <prop key="hibernate.cache.default_cache_concurrency_strategy">NONSTRICT_READ_WRITE</prop> 
     <prop key="hibernate.hbm2ddl.auto">update</prop> 
     <prop key="hibernate.jdbc.batch_size">1000</prop> 
     <prop key="hibernate.show_sql">false</prop> 
     <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop> 
     <prop key="hibernate.search.default.directory_provider">filesystem</prop> 
     <prop key="hibernate.search.default.indexBase">/hibernate-search</prop> 
     </props> 
    </property> 
    </bean> 

Środowisko

  • JDK6
  • Linux x64
  • Hibernate 4.1.10
  • Wiosna 3.2.1

UPDATE: Wykorzystanie @MappedSuperclass

@MappedSuperclass 
@Inheritance(strategy = InheritanceType.JOINED) 
public abstract class LongIdEntity { ... } 

Nie bądź zmieni.

+0

można sprawdzić, czy [to pytanie] (http://stackoverflow.com/questions/4452242/specifying-global-ehcache-capacity) nie rozwiązuje ten sam problem jak ten, który masz? – mindas

+0

Staram się naprawdę przeciwnie. Próbuje mieć jedną dużą pamięć podręczną i próbuję mieć pamięć podręczną dla każdej jednostki. Lub zastąp to zachowanie za pomocą @Cache (region = ....). Wcześniej tak działało, ale dziś jest ignorowane. –

Odpowiedz

7

Hibernate buforuje całą hierarchię podmiotów w jednym regionie wyraźnie. Nie ma nad tym kontroli. Jest to jedyny sposób prawidłowej obsługi buforowanej rozdzielczości polimorficznych odnośników. Inni dostawcy (jak sądzę) zezwalają na pewną kontrolę nad tym, gdzie/jak każda podklasa jest buforowana (przynajmniej to jest moje przypuszczenie oparte na opcjach dostarczonych przez JPA).

+0

Nieprawda. Zrobiłem to w przeszłości. Mam sugestię, aby wypróbować inną strategię dziedziczenia. Ale nie widzę, co to naprawdę ma wspólnego z buforowaniem. –

+6

Jestem głównym programistą Hibernate. Zapewniam cię, że buforuje całą mapowaną hierarchię w jednym regionie. I uczynił tak każdy ponieważ była buforowanie;) –

+0

patrzeć na to https://forum.hibernate.org/viewtopic.php?f=1&t=1025577 :-) –

1

miałem ten problem, i szukając internet mam kończącym się w tym wątku Stackoverflow. To naprawdę pouczające dla mnie, ponieważ mam ten sam problem, który wyjaśniłem w tym pytaniu. Czytanie dyskusji między Steve'em Ebersolem a Janem Goyvaertsem przemawia do rozwiązania mojej sprawy. Specjalnie link podany przez jedną z nich do Hibernate forum.

Testowanie zalecenia forum (również przeszła trzy lata od tego pytania, to chyba coś się zmieniło) Mam sukces w generowaniu różne regiony pamięci podręcznej dla różnych dzieci klasy nadrzędnej.

W moim przypadku rozwiązanie wykorzystywało @MappedSuperclassusuwania@Inheritance(strategy = InheritanceType.JOINED). W takim przypadku widzę prawidłowe trafienia we właściwych obszarach.

Dla porównania, mój kod jest podobny do tego:

@MappedSuperclass 
public abstract class ParentObject implements Serializable { 
    .... 


@Entity 
@Cacheable(true) 
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
public class ChildObject extends ParentObject { 
    .... 

Teraz w dzienniku widzę:

Cache: com.<...>.ChildObject store hit for com.<...>.ChildObject#52 

Zamiast:

Cache: com.<...>.ParentObject store hit for com.<...>.ParentObject#52 

Oczywiście, zmiana te adnotacje mają inne zachowanie niż używane w pytaniu i nie są pożądane w niektórych przypadkach. Ale nadal uważam, że warto, aby ta uwaga została tu dodana w przyszłości. Może może pomóc innej osobie.

+0

Czy jesteś pewien, że '@Inheritance (strategia = InheritanceType.TABLE_PER_CLASS)' jest naprawdę potrzebne? Klasa @MappedSuperclass nie wymaga adnotacji '@ Inheritance'. – Thierry

+0

Masz rację, nie ma tego przykładu. Używam tego kodu, aby uniknąć tworzenia tabeli dla niektórych pośrednich klas abstrakcyjnych, ponieważ zapomniałem dodać również '@ MappedSuperclass' do tych klas pośrednich. Naprawiam to również w moim kodzie i aktualizuję tę odpowiedź.Rozwiązaniem nie jest wstawianie '@Inheritance (strategy = InheritanceType.TABLE_PER_CLASS)', ale usunięcie '@Inheritance (strategy = InheritanceType.JOINED)' – JorgeHortelano

Powiązane problemy