/
BaseEntityRepository.java
147 lines (134 loc) · 5.87 KB
/
BaseEntityRepository.java
1
2
3
4
5
6
7
8
9
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.jpa.repository;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTenantAwareBaseEntity;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.lang.Nullable;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.EntityManager;
/**
* Command repository operations for all {@link TenantAwareBaseEntity}s.
*
* @param <T>
* type if the entity type
*/
@NoRepositoryBean
@Transactional(readOnly = true)
public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity>
extends PagingAndSortingRepository<T, Long>, CrudRepository<T, Long>, JpaSpecificationExecutor<T>,
NoCountSliceRepository<T>, ACMRepository<T> {
/**
* Overrides
* {@link org.springframework.data.repository.CrudRepository#findAll()}
* to return a list of found entities instead of an instance of
* {@link Iterable} to be able to work with it directly in further code
* processing instead of converting the {@link Iterable}.
*
* @return the found entities
*/
@Override
List<T> findAll();
/**
* Overrides
* {@link org.springframework.data.repository.CrudRepository#findAllById(Iterable)}
* to return a list of found entities instead of an instance of
* {@link Iterable} to be able to work with it directly in further code
* processing instead of converting the {@link Iterable}.
*
* @param ids to search in the database for
* @return the found entities
*/
@Override
List<T> findAllById(final Iterable<Long> ids);
/**
* Overrides
* {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)}
* to return a list of created entities instead of an instance of
* {@link Iterable} to be able to work with it directly in further code
* processing instead of converting the {@link Iterable}.
*
* @param entities to persist in the database
* @return the created entities
*/
@Override
@Transactional
<S extends T> List<S> saveAll(Iterable<S> entities);
// TODO When we switch to Spring 3.0 probably we could remove extending methods using
// queries and make here a default implementation using JPASpecificationExecutor delete method
// TODO To be considered if this method is needed at all
/**
* Deletes all entities of a given tenant from this repository. For safety
* reasons (this is a "delete everything" query after all) we add the tenant
* manually to query even if this will be done by {@link EntityManager}
* anyhow. The DB should take care of optimizing this away.
* <p/>
*
* @param tenant to delete data from
*/
void deleteByTenant(String tenant);
/**
* Returns a wrapper (or the same instance if access controller is <code>null</code> of this repository that
* supports ACM.
* <p/>
* Note: To use ACM support the returned object shall be used! <code>this</code> object will not achieve ACM
* support!
* <p/>
* Notes on ACM support (if enabled, i.e. <code>accessController</code> is not <code>null</code>):
* <ul>
* <li>ACM is applied for all {@link BaseEntityRepository} methods</li>
* <li>ACM is applied for all <code>findXXX</code> methods that returns {@link Iterable}
* (expected of <code>? extends T</code>),
* <code>? extends T</code> or {@link java.util.Optional}(expected of <code>? extends T</code>).
* </li>
* <li>For all other methods defined on repository interface level that are implemented, for instance,
* via {@link org.springframework.data.jpa.repository.Query} or using naming conventions
* (existsBySomething) the ACM won't be applied!
* </li>
* </ul>
*
* @param accessController access controller to be applied to the result
* @param entityType the entity type of the repository
* @return a repository that supports ACM.
*/
default BaseEntityRepository<T> withACM(@Nullable final AccessController<T> accessController) {
if (accessController == null) {
return this;
} else {
return BaseEntityRepositoryACM.of(this, accessController);
}
}
default <T extends AbstractJpaTenantAwareBaseEntity> Specification<T> byIdSpec(final Long id) {
return (root, query, cb) -> cb.equal(root.get(AbstractJpaBaseEntity_.id), id);
}
default <T extends AbstractJpaTenantAwareBaseEntity> Specification<T> byIdsSpec(final Iterable<Long> ids) {
final Collection<Long> collection;
if (ids instanceof Collection<Long>) {
collection = (Collection<Long>) ids;
} else {
collection = new LinkedList<>();
ids.forEach(collection::add);
}
return (root, query, cb) -> root.get(AbstractJpaBaseEntity_.id).in(collection);
}
default Optional<AccessController<T>> getAccessController() {
return Optional.empty();
}
}