Skip to content

Commit bc4474c

Browse files
authored
feat: properly handling repository inheritance (with specific-to-generic precedence) (#116)
1 parent 790bc6d commit bc4474c

File tree

5 files changed

+45
-9
lines changed

5 files changed

+45
-9
lines changed

tzatziki-spring-jpa/src/main/java/com/decathlon/tzatziki/steps/SpringJPASteps.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,14 @@ public void before() {
6767
if (crudRepositoryByClass == null) {
6868
crudRepositoryByClass = spring.applicationContext().getBeansOfType(CrudRepository.class).values()
6969
.stream()
70-
.<Map.Entry<Class<?>, CrudRepository<?, ?>>>mapMulti((crudRepository, consumer) -> {
71-
Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(crudRepository.getClass(), CrudRepository.class);
72-
Type type = typeArguments.get(CrudRepository.class.getTypeParameters()[0]);
73-
70+
.map(crudRepository -> Map.entry(crudRepository, TypeUtils.getTypeArguments(crudRepository.getClass(), CrudRepository.class).get(CrudRepository.class.getTypeParameters()[0])))
71+
.sorted((e1, e2) -> {
72+
if(e1.getValue() instanceof Class) return -1;
73+
return e2.getValue() instanceof Class ? 1 : 0;
74+
})
75+
.<Map.Entry<Class<?>, CrudRepository<?, ?>>>mapMulti((crudRepositoryWithType, consumer) -> {
76+
CrudRepository<?, ?> crudRepository = crudRepositoryWithType.getKey();
77+
Type type = crudRepositoryWithType.getValue();
7478
if (type instanceof TypeVariable<?> typeVariable) {
7579
type = typeVariable.getBounds()[0];
7680
TypeParser.getSubtypesOf((Class<?>) type)
@@ -81,7 +85,8 @@ public void before() {
8185
})
8286
.collect(Collectors.toMap(
8387
Map.Entry::getKey,
84-
Map.Entry::getValue
88+
Map.Entry::getValue,
89+
(v1, v2) -> v1
8590
));
8691
}
8792
if (entityClassByTableName == null) {
@@ -234,7 +239,9 @@ private Type entityTypeByTableNameOrClassName(String entityTableOrClass) {
234239

235240
public <E> CrudRepository<E, ?> getRepositoryByType(Type type) {
236241
if (Types.isAssignableTo(type, CrudRepository.class)) {
237-
return spring.applicationContext().getBean(Types.rawTypeOf(type));
242+
return ((CrudRepository<E, ?>) spring.applicationContext().getBeansOfType(Types.rawTypeOf(type)).values().stream()
243+
.sorted((b1, b2) -> b1.getClass() == type ? -1 : 1)
244+
.findFirst().get());
238245
}
239246
throw new AssertionError(type + " is not a CrudRepository!");
240247
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.decathlon.tzatziki.app.aspects;
2+
3+
import org.aspectj.lang.ProceedingJoinPoint;
4+
import org.aspectj.lang.annotation.Around;
5+
import org.aspectj.lang.annotation.Aspect;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.context.annotation.EnableAspectJAutoProxy;
8+
import com.decathlon.tzatziki.app.model.SuperUser;
9+
10+
import java.util.Arrays;
11+
12+
@Aspect
13+
@Configuration
14+
@EnableAspectJAutoProxy
15+
public class SuperUserCrudSavePrefixerAspect {
16+
@Around(value = "execution(* com.decathlon.tzatziki.app.dao.SuperUserDataSpringRepository.saveAll(..))")
17+
public Object addPrefixToRoles(ProceedingJoinPoint joinPoint) throws Throwable {
18+
((Iterable<SuperUser>) Arrays.stream(joinPoint.getArgs()).findFirst().get()).forEach(superUser -> superUser.setRole("superUser_"+superUser.getRole()));
19+
return joinPoint.proceed();
20+
}
21+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.decathlon.tzatziki.app.dao;
2+
3+
import com.decathlon.tzatziki.app.model.SuperUser;
4+
5+
6+
public interface SuperUserDataSpringRepository extends UserDataSpringRepository<SuperUser> {}

tzatziki-spring-jpa/src/test/java/com/decathlon/tzatziki/app/model/SuperUser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import lombok.Getter;
44
import lombok.NoArgsConstructor;
5+
import lombok.Setter;
56

67
import javax.persistence.Column;
78
import javax.persistence.Entity;
@@ -12,6 +13,7 @@
1213
@NoArgsConstructor
1314
@Table(name = "super_users")
1415
public class SuperUser extends User {
16+
@Setter
1517
@Column(name = "role")
1618
String role;
1719
}

tzatziki-spring-jpa/src/test/resources/com/decathlon/tzatziki/steps/spring-jpa.feature

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@ Feature: to interact with a spring boot service having a persistence layer
237237
| 1 | Darth | Vader | admin |
238238
| 2 | Anakin | Skywalker | dummy |
239239
Then the super_users table contains:
240-
| id | firstName | lastName | role |
241-
| 1 | Darth | Vader | admin |
242-
| 2 | Anakin | Skywalker | dummy |
240+
| id | firstName | lastName | role |
241+
| 1 | Darth | Vader | superUser_admin |
242+
| 2 | Anakin | Skywalker | superUser_dummy |
243243

244244
Scenario: if we have a table which is handled by multiple entities, we should prioritize entity types from default parser package
245245
# non-default package, should not be used and throw an exception

0 commit comments

Comments
 (0)