2012-08-09 42 views
104

Estoy buscando en Spring Data JPA. Considere el siguiente ejemplo en el que obtendré toda la funcionalidad crud y finder funcionando por defecto y si quiero personalizar un buscador, eso también se puede hacer fácilmente en la interfaz misma.Cómo agregar un método personalizado a Spring Data JPA

@Transactional(readOnly = true) 
public interface AccountRepository extends JpaRepository<Account, Long> { 

    @Query("<JPQ statement here>") 
    List<Account> findByCustomer(Customer customer); 
} 

Me gustaría saber cómo puedo agregar un método personalizado completo con su implementación para el AccountRepository anterior? Como es una Interfaz, no puedo implementar el método allí.

Respuesta

175

Es necesario crear una interfaz independiente para sus métodos personalizados:

public interface AccountRepository 
    extends JpaRepository<Account, Long>, AccountRepositoryCustom { ... } 

public interface AccountRepositoryCustom { 
    public void customMethod(); 
} 

y proporcionar una clase de implementación para esa interfaz:

public class AccountRepositoryImpl implements AccountRepositoryCustom { 

    @Autowired 
    AccountRepository accountRepository; /* Optional - if you need it */ 

    public void customMethod() { ... } 
} 

Ver también:

+14

¿Puede esta implementación personalizada inyectar el repositorio real, por lo que puede utilizar los métodos definidos allí? Específicamente, me gustaría hacer referencia a varias funciones de find * definidas en la interfaz del repositorio en una implementación de hallazgo de nivel superior. Como esas funciones de find *() no tienen una implementación, no puedo declararlas en la interfaz personalizada o en la clase Impl. – JBCP

+14

He seguido esta respuesta, desafortunadamente ahora Spring Data está tratando de encontrar la propiedad "customMethod" en mi objeto "Cuenta" ya que está tratando de generar automáticamente una consulta para todos los métodos definidos en el AccountRepository. ¿Alguna forma de detener esto? –

+26

@NickFoote tenga en cuenta que el nombre de la clase que implementa su repositorio debe ser: 'AccountRepositoryImpl' no:' AccountRepositoryCustomImpl', etc. - es una convención de nomenclatura muy estricta. – Xeon

53

además de axtavt de answer, no olvide que usted puede inyectar entidad gestora en su implementación personalizada si lo necesita para construir sus consultas:

public class AccountRepositoryImpl implements AccountRepositoryCustom { 

    @PersistenceContext 
    private EntityManager em; 

    public void customMethod() { 
     ... 
     em.createQuery(yourCriteria); 
     ... 
    } 
} 
+7

Gracias, sin embargo, quiero saber cómo usar Pageable y Page en la implementación personalizada. ¿Alguna entrada? –

+2

Gracias por agregar este tidbit ... Lo necesitaba :) – testing123

3

Si usted quiere ser capaz de hacer más sofisticada operaciones que puede necesitar el acceso a la parte interna de la primavera de datos, en cuyo caso las siguientes obras (como mi solución provisional a DATAJPA-422):

public class AccountRepositoryImpl implements AccountRepositoryCustom { 

    @PersistenceContext 
    private EntityManager entityManager; 

    private JpaEntityInformation<Account, ?> entityInformation; 

    @PostConstruct 
    public void postConstruct() { 
     this.entityInformation = JpaEntityInformationSupport.getMetadata(Account.class, entityManager); 
    } 

    @Override 
    @Transactional 
    public Account saveWithReferenceToOrganisation(Account entity, long referralId) { 
     entity.setOrganisation(entityManager.getReference(Organisation.class, organisationId)); 
     return save(entity); 
    } 

    private Account save(Account entity) { 
     // save in same way as SimpleJpaRepository 
     if (entityInformation.isNew(entity)) { 
      entityManager.persist(entity); 
      return entity; 
     } else { 
      return entityManager.merge(entity); 
     } 
    } 

} 
5

Im utilizando el siguiente código de acceso con el fin de encontrar métodos generan a partir de mi implem personalizada Entation. Obtener la implementación a través de la fábrica de frijoles evita problemas de creación circular de frijol.

public class MyRepositoryImpl implements MyRepositoryExtensions, BeanFactoryAware { 

    private BrandRepository myRepository; 

    public MyBean findOne(int first, int second) { 
     return myRepository.findOne(new Id(first, second)); 
    } 

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 
     myRepository = beanFactory.getBean(MyRepository.class); 
    } 
} 
2

Teniendo en cuenta el fragmento de código, tenga en cuenta que sólo se puede pasar objetos nativos con el método findBy ###, digamos que usted quiere cargar una lista de cuentas que pertenece ciertos clientes, una solución consiste en hacer esto ,

@Query("Select a from Account a where a."#nameoffield"=?1") 
     List<Account> findByCustomer(String "#nameoffield"); 

Hacer que el nombre de la tabla que se va a consultar es el mismo que la clase Entity. Para otras implementaciones, consulte this

+1

El es un error tipográfico en la consulta, debe ser nameoffie * l * d, no tengo el derecho de corregirlo. – BrunoJCM

+0

este código ni siquiera compila – memozac

2

Hay otro problema que debe tenerse en cuenta aquí. Algunas personas esperan que agregar un método personalizado a su repositorio las exponga automáticamente como servicios REST en el enlace '/ buscar'. Desafortunadamente, este no es el caso. Spring no es compatible con eso actualmente.

esto es 'por diseño' característica, el descanso de primavera comprueba los datos de forma explícita si el método es un método personalizado y no expone como un enlace de búsqueda RESTO:

private boolean isQueryMethodCandidate(Method method) {  
    return isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method); 
} 

Ésta es una cotización de Oliver Gierke:

Esto es por diseño. Los métodos de repositorio personalizados no son métodos de consulta como que pueden implementar efectivamente cualquier comportamiento.Por lo tanto, actualmente es imposible para nosotros decidir sobre el método HTTP para exponer el método debajo. POST sería la opción más segura, pero eso no está en línea con los métodos de consulta genéricos (que reciben GET).

Para más detalles ver este tema: https://jira.spring.io/browse/DATAREST-206

+0

Eso es desafortunado, he perdido tanto tiempo tratando de averiguar, lo que hice mal, y finalmente, entiendo que no existe tal característica. ¿Por qué incluso implementarían esa funcionalidad? Para tener menos frijoles? ¿Tener todos los métodos de dao en un solo lugar? Pude haberlo logrado de otras maneras. ¿Alguien sabe cuál es el objetivo de la función "agregar comportamiento a los repositorios individuales"? – Skeeve

6

Esta es limitado en su uso, pero por métodos personalizados simples que usted puede utilizar predeterminado métodos de interfaz como:

import demo.database.Customer; 
import org.springframework.data.repository.CrudRepository; 

public interface CustomerService extends CrudRepository<Customer, Long> { 


    default void addSomeCustomers() { 
     Customer[] customers = { 
      new Customer("Józef", "Nowak", "[email protected]", 679856885, "Rzeszów", "Podkarpackie", "35-061", "Zamknięta 12"), 
      new Customer("Adrian", "Mularczyk", "[email protected]", 867569344, "Krosno", "Podkarpackie", "32-442", "Hynka 3/16"), 
      new Customer("Kazimierz", "Dejna", "[email protected]", 996435876, "Jarosław", "Podkarpackie", "25-122", "Korotyńskiego 11"), 
      new Customer("Celina", "Dykiel", "[email protected]", 947845734, "Żywiec", "Śląskie", "54-333", "Polna 29") 
     }; 

     for (Customer customer : customers) { 
      save(customer); 
     } 
    } 
} 

EDIT:

En this spring tutorial está escrito:

Spring Data JPA también le permite definir otros métodos de consulta por simplemente declarando su firma de método.

Por lo tanto, es posible incluso simplemente declarar como método:

Customer findByHobby(Hobby personHobby); 

y si Hobby objeto es una propiedad del cliente a continuación, primavera, determinará automáticamente método para usted.

Cuestiones relacionadas