2012-12-29 1 views
3

J'ai deux entités Livre et Auteur. Le livre a une collection d'auteurs. J'utilise le cache de second niveau pour conserver l'entité Livre avec ses auteurs. Lors du débogage, je peux voir qu'il se passe putForExternalRead pour l'instance du livre et chaque auteur dans la collection. Mais quand j'appelle à nouveau la méthode find(Book.class, ISBN) il utilise le cache juste pour le livre tandis que la collection d'auteurs est récupérée chaque fois de la base de données. Chaque fois que la collection d'auteurs est mise dans le cache de second niveau. S'il vous plaît laissez-moi savoir s'il y en a où je dois changer la stratégie d'accès au cache pour la collecte. J'utilise Jboss 6.0 Infinispan 5. et postgres 9 DBMS.Hibernate Collection cache: Comment utiliser?

Voici mon code

package bookentity.ejb; 

/* * Pour changer ce modèle, choisissez Outils | Modèles * et ouvrez le modèle dans l'éditeur. */

import java.io.Serializable; 
import java.util.ArrayList; 
import javax.persistence.Cacheable; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.Table; 
import javax.persistence.ManyToMany; 
import javax.persistence.JoinTable; 
//import javax.persistence.JoinColumns; 
import javax.persistence.JoinColumn; 
import java.util.Collection; 
import java.util.List; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
//import javax.persistence.inv 
import javax.persistence.OneToMany; 



@Entity 
@Cacheable 
@Table(name = "BOOK") 
@NamedQueries({@NamedQuery(name="findBookByAuthorName",query="SELECT b FROM Book b,   Author a WHERE a.authorName=:authorName AND b = SOME(SELECT x FROM a.books x)"), 
@NamedQuery(name="findBookByTitle",query="SELECT b FROM Book b WHERE b.title=:bTitle")}) 

public class Book implements Serializable { 
private static final long serialVersionUID = 1L; 
@Id 
private int ISBN; 
private String title; 
private String description; 
private Author author; 
// @ManyToMany(fetch=FetchType.LAZY) 
@ManyToMany(fetch=FetchType.EAGER) 
@JoinTable(name="BOOK_AUTHOR", [email protected](name="BOOK_ID"), 
[email protected](name="AUTHOR_ID")) 
private Collection<Author> authors; 



//@OneToMany(fetch=FetchType.EAGER, mappedBy="bookEntity") 
    @OneToMany(fetch=FetchType.LAZY, mappedBy="bookEntity") 
public Collection<Review> reviews; 

    public Book() { 
    authors = new ArrayList<Author>(); 
    reviews = new ArrayList<Review>(); 
} 


public int getISBN() { 
    return ISBN; 
} 


public void setISBN(int ISBN) { 
    this.ISBN = ISBN; 
} 
public String getTitle(){ 
    return title; 
} 

public void setTitle(String title){ 
    this.title = title; 
} 

    public String getDescription(){ 
    return description; 
} 

public void setDescription(String description){ 
    this.description = description; 
} 
public void addReview(Review review){ 
    if(!getReviews().contains(review)){ 
     getReviews().add(review); 

    if(review.getBookEntity()!=null){ 
     review.getBookEntity().getReviews().remove(this); 
    } 
     review.setBookEntity(this); 
    } 
} 
public void addAuthor(Author author){ 
    if (!getAuthors().contains(author)){ 
      getAuthors().add(author); 
     } 
    if(!author.getBooks().contains(this)){ 
     author.getBooks().add(this); 
    } 
} 

public Collection<Review> getReviews(){ 
    return reviews; 
} 


public Collection<Author> getAuthors(){ 

    return authors; 
    } 

    void setAuhorId(int authorID) { 

    } 


} 

Voici le code Auteur entité

package bookentity.ejb; 

import java.io.Serializable; 
import java.util.ArrayList; 
import javax.persistence.Cacheable; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.ManyToMany; 
import java.util.Collection; 
import java.util.Hashtable; 
import java.util.List; 
import javax.naming.Context; 
import javax.naming.InitialContext; 


@Entity 
@Cacheable 
public class Author implements Serializable { 
private static final long serialVersionUID = 1L; 
@Id 
private int author_id; 
String authorName; 
String authAddress; 
@ManyToMany(mappedBy = "authors") 
private Collection<Book> books; 

public Author() { 
    books = new ArrayList<Book>(); 
} 



public void setAuthor_id(int author_id) { 
    this.author_id = author_id; 

} 


public int getAuthorId() { 
    return this.author_id; 
} 

public void setAuthorName(String authorName) { 
    this.authorName = authorName; 
} 

public String getAuthorName() { 
    return authorName; 
} 
public String getAuthorAddress(){ 
    return this.authAddress; 
} 
public void setAuthorAddress(String authAddress){ 
    this.authAddress = authAddress; 
} 

public Collection<Book> getBooks() { 
    return books; 

} 


public void addBook(Book book){ 
    if(!getBooks().contains(book)) { 
    getBooks().add(book); 
    //book.getAuthors().add(this); 
    } 
if (!book.getAuthors().contains(this)){ 
    book.getAuthors().add(this); 
    } 
} 

} 

Voici le fichier persistence.xml

<?xml version="1.0" encoding="UTF-8"?> 
<persistence 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_1_0.xsd" 
version="1.0"> 
<persistence-unit name="BookAuthorApp3-ejbPU" transaction-type="JTA"> 
<provider>org.hibernate.ejb.HibernatePersistence</provider> 
<jta-data-source>java:/PostgresDS</jta-data-source> 
<properties> 
<property name="hibernate.hbm2ddl.auto" value="update"/> 
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/> 
<property name="hibernate.session_factory_name" value="SessionFactories/infinispan1" /> 
<property name="javax.persistence.sharedCache.mode" value="ALL" /> 
<property name="hibernate.cache.use_second_level_cache" value="true" /> 
<property name="hibernate.cache.use_query_cache" value="true" /> 
<property name="hibernate.cacheable" value="true" /> 
<property name="hibernate.cache.use_structured_entries" value="true" /> 
<property name="hibernate.cache.infinispan.collection.cfg" value="entity" /> 
<property name="hibernate.cache.infinispan.bookentity.ej.Book.cfg" value="Books"/> 
<property name="hibernate.cache.infinispan.bookentity.ej.Book.authors.cfg" value="Authors"/> 
<property name="hibernate.cache.infinispan.statistics" value="true"/> 
<property name="hibernate.generate_statistics" value="true" /> 
<property name="hibernate.cache.region_prefix" value="infinispan" /> 
<property name="hibernate.cache.infinispan.entity.cfg" value="entity" /> 
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory" /> 
<property name="hibernate.cache.infinispan.cachemanager" value="java:CacheManager/entity" /> 
</properties> 

Voici le fichier Infinispan-configs.xml

<infinispan-config name="hibernate" jndi-name="java:CacheManager/entity"> 
<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="urn:infinispan:config:5.0 http://www.infinispan.org/schemas/infinispan-config-5.0.xsd" 
xmlns="urn:infinispan:config:5.0"> 
<global> 
<transport clusterName="${jboss.partition.name:DefaultPartition}-Hibernate" distributedSyncTimeout="17500"> 
<properties> 
    <property name="stack" value="${jboss.default.jgroups.stack:udp}"/> 
</properties> 
</transport> 
<globalJmxStatistics enabled="true"/> 
<shutdown hookBehavior="DONT_REGISTER"/> 
</global> 
<default> 
    <jmxStatistics enabled="false"/> 
    <!--transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossTransactionManagerLookup"/--> 
</default> 
<namedCache name="entity"> 
    <clustering mode="invalidation"> 
    <stateRetrieval fetchInMemoryState="false" timeout="20000"/> 
    <sync replTimeout="20000"/> 
    </clustering> 
    <locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" 
      lockAcquisitionTimeout="15000" useLockStriping="false" /> 
    <eviction wakeUpInterval="5000" maxEntries="10000" strategy="LRU"/> 
    <expiration lifespan = "-1" maxIdle="-1"/> 
    <lazyDeserialization enabled="true"/> 
</namedCache> 

Répondre

4

Le La collection elle-même doit être mise en cache en utilisant l'annotation @Cache. Voir the documentation:

Hibernate vous permet également de mettre en cache le contenu d'une collection ou les identifiants si la collection contient d'autres entités. Utilisez l'annotation @Cache sur la propriété de collection.

Exemple 21.6. collections à l'aide d'annotations Mise en cache

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
@JoinColumn(name="CUST_ID") 
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
public SortedSet<Ticket> getTickets() { 
    return tickets; 
}