конфигурация
Вы должны добавить следующую конфигурацию в файл конфигурации Spring Beans. Вы должны указать новый класс фабрики хранилища. Мы разработаем класс позже.
|
1
2
|
<jpa:repositories base-package='example.borislam.dao'factory-class='example.borislam.data.springData.DefaultRepositoryFactoryBean/> |
Просто разработайте интерфейс, расширяющий JpaRepository. Вы должны помнить, чтобы аннотировать это с @NoRepositoryBean.
|
1
2
3
4
|
@NoRepositoryBeanpublic interface GenericRepository <T, ID extends Serializable> extends JpaRepository<T, ID> { } |
Определить пользовательский базовый класс реализации репозитория
Следующим шагом является разработка настроенного базового класса репозитория. Вы можете видеть, что у меня есть только одно свойство (т.е. springDataRepositoryInterface) внутри этого настраиваемого базового репозитория. Я просто хочу получить больше контроля над поведением настраиваемого поведения интерфейса репозитория. Я покажу, как добавить больше возможностей этого базового класса репозитория в следующем посте.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
@SuppressWarnings('unchecked')@NoRepositoryBeanpublic class GenericRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements GenericRepository<T, ID> , Serializable{ private static final long serialVersionUID = 1L; static Logger logger = Logger.getLogger(GenericRepositoryImpl.class); private final JpaEntityInformation<T, ?> entityInformation; private final EntityManager em; private final DefaultPersistenceProvider provider; private Class<?> springDataRepositoryInterface; public Class<?> getSpringDataRepositoryInterface() { return springDataRepositoryInterface; } public void setSpringDataRepositoryInterface( Class<?> springDataRepositoryInterface) { this.springDataRepositoryInterface = springDataRepositoryInterface; } /** * Creates a new {@link SimpleJpaRepository} to manage objects of the given * {@link JpaEntityInformation}. * * @param entityInformation * @param entityManager */ public GenericRepositoryImpl (JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager , Class<?> springDataRepositoryInterface) { super(entityInformation, entityManager); this.entityInformation = entityInformation; this.em = entityManager; this.provider = DefaultPersistenceProvider.fromEntityManager(entityManager); this.springDataRepositoryInterface = springDataRepositoryInterface; } /** * Creates a new {@link SimpleJpaRepository} to manage objects of the given * domain type. * * @param domainClass * @param em */ public GenericRepositoryImpl(Class<T> domainClass, EntityManager em) { this(JpaEntityInformationSupport.getMetadata(domainClass, em), em, null); } public <S extends T> S save(S entity) { if (this.entityInformation.isNew(entity)) { this.em.persist(entity); flush(); return entity; } entity = this.em.merge(entity); flush(); return entity; } public T saveWithoutFlush(T entity) { return super.save(entity); } public List<T> saveWithoutFlush(Iterable<? extends T> entities) { List<T> result = new ArrayList<T>(); if (entities == null) { return result; } for (T entity : entities) { result.add(saveWithoutFlush(entity)); } return result; }} |
В качестве простого примера здесь я просто переопределил метод сохранения по умолчанию SimpleJPARepository. Поведение по умолчанию метода сохранения не сбрасывается после сохранения. Я изменил, чтобы сделать его флеш после сохранения. С другой стороны, я добавляю еще один метод с именем saveWithoutFlush (), чтобы позволить разработчику вызывать сохранение объекта без сброса.
Определить пользовательский репозиторий фабричного компонента
Последний шаг — создание класса фабричного компонента и класса фабрики для создания хранилища на основе настроенного вами базового класса хранилища.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
public class DefaultRepositoryFactoryBean <T extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> { /** * Returns a {@link RepositoryFactorySupport}. * * @param entityManager * @return */ protected RepositoryFactorySupport createRepositoryFactory( EntityManager entityManager) { return new DefaultRepositoryFactory(entityManager); }}/** * * The purpose of this class is to override the default behaviour of the spring JpaRepositoryFactory class. * It will produce a GenericRepositoryImpl object instead of SimpleJpaRepository. * */public class DefaultRepositoryFactory extends JpaRepositoryFactory{ private final EntityManager entityManager; private final QueryExtractor extractor; public DefaultRepositoryFactory(EntityManager entityManager) { super(entityManager); Assert.notNull(entityManager); this.entityManager = entityManager; this.extractor = DefaultPersistenceProvider.fromEntityManager(entityManager); } @SuppressWarnings({ 'unchecked', 'rawtypes' }) protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository( RepositoryMetadata metadata, EntityManager entityManager) { Class<?> repositoryInterface = metadata.getRepositoryInterface(); JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType()); if (isQueryDslExecutor(repositoryInterface)) { return new QueryDslJpaRepository(entityInformation, entityManager); } else { return new GenericRepositoryImpl(entityInformation, entityManager, repositoryInterface); //custom implementation } } @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { if (isQueryDslExecutor(metadata.getRepositoryInterface())) { return QueryDslJpaRepository.class; } else { return GenericRepositoryImpl.class; } } /** * Returns whether the given repository interface requires a QueryDsl * specific implementation to be chosen. * * @param repositoryInterface * @return */ private boolean isQueryDslExecutor(Class<?> repositoryInterface) { return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class .isAssignableFrom(repositoryInterface); } } |
Вывод
Теперь вы можете добавить больше возможностей в базовый класс репозитория. Теперь в вашей программе вы можете создать свой собственный интерфейс репозитория, расширяющий GenericRepository вместо JpaRepository.
|
1
2
3
4
|
public interface MyRepository <T, ID extends Serializable> extends GenericRepository <T, ID> { void someCustomMethod(ID id); } |
В следующем посте я покажу вам, как добавить функции фильтра гибернации в этот GenericRepository.
Ссылка: Настройка репозитория Spring Data JPA от нашего партнера JCG Бориса Лама в блоге Programming Peaceful .