Sto considerando i dati di primavera per un progetto. È possibile sovrascrivere il metodo di salvataggio generato per impostazione predefinita? E se si, come?Dati primaverili: metodo di sostituzione dell'override
risposta
Non ha funzionato correttamente, quindi ho inserito la logica necessaria in una classe di servizio e ho lasciato invariato il metodo di salvataggio dei repository.
Credo che si estende SimpleJpaRepository:
public class **CustomSimpleJpaRepository** extends SimpleJpaRepository {
@Transactional
public <S extends T> S save(S entity) { //do what you want instead }
}
quindi assicurarsi che questo è usato al posto del SimpleJpaRepository predefinito estendendo:
public class CustomJpaRepositoryFactory extends JpaRepositoryFactory {
protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) {
Class<?> repositoryInterface = metadata.getRepositoryInterface();
JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
SimpleJpaRepository<?, ?> repo = isQueryDslExecutor(repositoryInterface) ? new QueryDslJpaRepository(
entityInformation, entityManager) : new CustomSimpleJpaRepository(entityInformation, entityManager);
repo.setLockMetadataProvider(lockModePostProcessor.getLockMetadataProvider());
return repo;
}
}
Non ancora fatto, abbiamo anche bisogno di avere la tua propria fabbrica bean per utilizzarlo nella configurazione xml:
public class CustomRepositoryFactoryBean <T extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new **CustomJpaRepositoryFactory**(entityManager);
}
}
config:
<jpa:repositories base-package="bla.bla.dao" factory-class="xxxx.**CustomRepositoryFactoryBean**"/>
Speranza che aiuta.
Il metodo 'isQueryDslExecutor()' sembra essere un codice privato e la classe 'LockModePostProcessor' non esiste.Ho il' LockModeRepositoryPostProcessor' con lo stesso metodo. Questo cosa intendevi? – coderatchet
Utilizzare listener di eventi JPA come @PrePersist, @PreUpdate. Ciò funzionerà se il provider JPA sottostante supporta queste funzionalità. Questa è la caratteristica di JPA 2, quindi l'ultima versione di Hibernate, EclipseLink ecc. Dovrebbe supportarla.
Questo non funziona perché la logica/codice che deve essere eseguito deve accedere al database e non voglio avere riferimenti al livello di accesso ai dati nelle mie classi di entità. –
Ci sono diversi problemi. Innanzitutto, queste annotazioni potrebbero avere un comportamento specifico del provider; secondo, sono molto limitati in quello che possono fare; in terzo luogo, questo non risponde all'opinione pubblica perché non è collegato ai dati primaverili; e, infine, nessuna di queste annotazioni ha lo scopo di scavalcare il metodo di salvataggio, nemmeno il metodo persistito di JPA per tutto ciò che vale. Questa risposta dovrebbe essere ampiamente ridimensionata. –
Semplicemente crea la tua interfaccia personalizzata come al solito e dichiara i metodi che vuoi sovrascrivere con la stessa firma di quella esposta da CrudRepository
(o JpaRepository
, ecc.). Supponiamo di avere un MyEntity
un'entità e un repository MyEntityRepository
e si desidera ignorare l'auto-generata save
metodo predefinito di MyEntityRepository
che prende un solo esempio entità, quindi definire:
public interface MyEntityRepositoryCustom {
<S extends MyEntity> S save(S entity);
}
e implementare questo metodo come ti piace nella tua MyEntityRepositoryImpl
, come al solito:
@Transactional
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
public <S extends MyEntity> S save(S entity) {
// your implementation
}
}
E poi, come al solito, diamo MyEntityRepository
implementare MyEntityRepositoryCustom
.
In questo modo, Spring Data JPA chiamerà il metodo save
del proprio MyEntityRepositoryImpl
invece dell'implementazione predefinita. Almeno questo funziona per me con il metodo delete
in Spring Data JPA 1.7.2.
Questo funziona davvero. Un bit importante per farlo funzionare è conservare la convenzione di denominazione. Cioè, il nome della classe MyEntityRepositoryImpl deve essere costruito come '
Fresco, ma come si chiama il metodo JPARepository.save predefinito da MyEntityRepositoryImpl? –
@DanielPinyol Hai lasciato Spring iniettare il gestore di entità nel tuo 'MyEntityRepositoryImpl' e quindi richiamare' persist (Object) 'su di esso, piuttosto che sull'implementazione predefinita' JPARepository'. È possibile utilizzare '@ PersistenceContext' per questo scopo. –
Per fornire l'override del metodo di salvataggio generato predefinito, è necessario utilizzare l'aggregazione dell'implementazione del repository Spring Data all'interno dell'implementazione del repository personalizzato.
interfaccia Repository:
public interface UserRepository extends CrudRepository<User, String>{
}
Il repository implementazione:
@Repository("customUserRepository")
public class CustomUserRepository implements UserRepository {
@Autowired
@Qualifier("userRepository") // inject Spring implementation here
private UserRepository userRepository;
public User save(User user) {
User user = userRepository.save(entity);
// Your custom code goes here
return user;
}
// Delegate other methods here ...
@Override
public User findOne(String s) {
return userRepository.findOne(s);
}
}
quindi utilizzare l'un'implementazione personalizzata nel vostro servizio:
@Autowired
@Qualifier("customUserRepository")
private UserRepository userRepository;
Questo potrebbe essere utile se si ar E intenzione di riutilizzare il metodo originale. È sufficiente iniettare EntityManager
nella classe di implementazione.
public interface MyEntityRepositoryCustom {
<S extends MyEntity> S save(S entity);
}
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
// optionally specify unitName, if there are more than one
@PersistenceContext(unitName = PRIMARY_ENTITY_MANAGER_FACTORY)
private EntityManager entityManager;
/**
* @see org.springframework.data.jpa.repository.support.SimpleJpaRepository
*/
@Transactional
public <S extends MyEntity> S save(S entity) {
// do your logic here
JpaEntityInformation<MyEntity, ?> entityInformation = JpaEntityInformationSupport.getMetadata(MyEntity.class, entityManager);
if (entityInformation.isNew(entity)) {
entityManager.persist(entity);
return entity;
} else {
return entityManager.merge(entity);
}
}
}
Cosa vuoi ottenere? Forse AOP è un approccio migliore? –
Non utilizzare ID per determinare se l'entità in questione è nuova o meno. l'entità è un significato immutabile se un utente lo modifica, il sistema dovrebbe crearne uno nuovo con i dati modificati (o usare quello esistente uguale a quei dati.) L'unica preoccupazione è che i dati primaverili + querydsl sembrano molto promettenti per il mio progetto. –
Cosa ne pensi dell'attuazione ['Persistable'] (http://static.springsource.org/spring-data/data-commons/docs/1.3.2.RELEASE/api/org/springframework/data/domain/Persistable.html) "Funzionerebbe anche per te?" Stai utilizzando Spring Data JPA o qualche altro database di back-end? –