2013-11-04 10 views
6

La documentazione Spring qui http://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/repositories.html#repositories.custom-implementations fornisce esempi per aggiungere funzionalità personalizzate a tutti i repository oa un singolo repository, non entrambi.Spring Jpa aggiunge funzionalità personalizzate a tutti i repository e allo stesso tempo altre funzioni personalizzate a un singolo repository

Supponiamo di voler aggiungere alcune funzioni personalizzate a tutti i repository (utilizzando Custom Repository Factory Bean) e altri solo a un singolo repository (i documenti dicono di utilizzare un'interfaccia personalizzata e una Impl personalizzata); Come posso raggiungere questo obiettivo?

Alcuni esempi di codice in cui ho aggiunto il metodo "setCurrentTenansInSession" a tutti i repository; ora voglio aggiungere un metodo personalizzato, ad es. "newCustomMethod", su un singolo repository (cioè un MyJpaRepository, come per il mio factory di repository personalizzato). Come faccio a fare questo?

personalizzato dell'interfaccia comportamento:

@NoRepositoryBean 
public interface MyJpaRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { 
    public void setCurrentTenantInSession(Object object);  
} 

implementazione comportamento personalizzato:

public class MultiTenantSimpleJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyJpaRepository<T, ID> { 
    public void setCurrentTenantInSession(Object object) { 
     //custom impl 
    } 
} 

personalizzato repository fabbrica di fagioli:

public class MultiTenantJpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> { 

    @Override 
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { 
     return new MultiTenantJpaRepositoryFactory(entityManager); 
    } 
} 

E infine la fabbrica repository personalizzato:

public class MultiTenantJpaRepositoryFactory extends JpaRepositoryFactory { 
    public MultiTenantJpaRepositoryFactory(EntityManager entityManager) { 
     super(entityManager); 
    } 

    @Override 
    protected JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) { 
     final JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType()); 

     final SimpleJpaRepository<?, ?> repo = new MultiTenantSimpleJpaRepository(entityInformation, entityManager); 

     repo.setLockMetadataProvider(LockModeRepositoryPostProcessor.INSTANCE.getLockMetadataProvider()); 
     return repo; 
    } 

    @Override 
    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { 
     return MultiTenantSimpleJpaRepository.class; 
    } 
} 

risposta

11

Hai solo bisogno di combinare gli approcci sulla pagina doc che hai citato. Lascia che sia Car l'entità per la quale desideri avere un repository personalizzato.

CommonCustomRepository definisce i metodi aggiunti a tutti i pronti contro termine:

@NoRepositoryBean 
public interface CommonCustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { 
    String getCustomValue(); 
} 

L'implementazione di questo repo:

public class CommonCustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CommonCustomRepository<T, ID> { 

    public CommonCustomRepositoryImpl(Class<T> domainClass, EntityManager em) { 
     super(domainClass, em); 
    } 

    public CommonCustomRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, 
      EntityManager entityManager) { 
     super(entityInformation, entityManager); 
    } 

    @Override 
    public String getCustomValue() { 
     return "CustomValue"; 
    } 

} 

metodi personalizzati per CarRepository

@NoRepositoryBean 
public interface CustomCarRepository { 

    public String getCustomCarValue(); 
} 

Attuazione del car- personalizzato metodi correlati

public class CarRepositoryImpl implements CustomCarRepository { 

    @PersistenceContext 
    private EntityManager em; 

    @Override 
    public String getCustomCarValue() { 
     return "CustomCarValue"; 
    } 
} 

L'interfaccia combinato per CarRepository

public interface CarRepository extends CommonCustomRepository<Car, Long>, CustomCarRepository { 
} 

personalizzato fabbrica di pronti contro termine, proprio come nella documentazione

public class CustomRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends 
    JpaRepositoryFactoryBean<R, T, I> { 

    @Override 
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { 

     return new CustomRepositoryFactory(entityManager); 
    } 

    private static class CustomRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory { 

     private EntityManager entityManager; 

     public CustomRepositoryFactory(EntityManager entityManager) { 
      super(entityManager); 

      this.entityManager = entityManager; 
     } 

     @Override 
     protected Object getTargetRepository(RepositoryMetadata metadata) { 

      return new CommonCustomRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager); 
     } 

     @Override 
     protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { 

      // The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory 
      // to check for QueryDslJpaRepository's which is out of scope. 
      return CommonCustomRepositoryImpl.class; 
     } 
    } 
} 

Il bit finale della configurazione, proprio come nella documentazione

<jpa:repositories base-package="com.example" factory-class="com.example.CustomRepositoryFactoryBean"/> 
+0

Grazie mille kkamenev! – lincetto

+2

A partire da 'spring-data-commons' 1.11 specificare' base-class = "com.example.CommonCustomRepositoryImpl" 'invece di deprecato attributo' factory-class' per 'jpa: repositories'. La produzione non è necessaria quando si specifica la classe base. –

Problemi correlati