SHOW:
|
|
- or go back to the newest paste.
1 | @Target({ | |
2 | ElementType.TYPE, | |
3 | ElementType.METHOD, | |
4 | }) | |
5 | @Retention(RetentionPolicy.RUNTIME) | |
6 | public @interface PreCollectionChange { | |
7 | } | |
8 | ||
9 | ||
10 | ||
11 | public class IntegratorImpl implements Integrator { | |
12 | ||
13 | private final Map<Class<?>, List<Method>> preCollectionChangeMethods; | |
14 | ||
15 | public IntegratorImpl() { | |
16 | this.preCollectionChangeMethods = new ConcurrentHashMap<>(); | |
17 | } | |
18 | ||
19 | @Override | |
20 | public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { | |
21 | EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class); | |
22 | registry.getEventListenerGroup(EventType.FLUSH_ENTITY).appendListener(new PreCollectionChangeFlushEntityEventListener()); | |
23 | } | |
24 | ||
25 | private class PreCollectionChangeFlushEntityEventListener implements FlushEntityEventListener { | |
26 | ||
27 | @Override | |
28 | public void onFlushEntity(FlushEntityEvent event) throws HibernateException { | |
29 | Object entity = event.getEntity(); | |
30 | Class<?> entityClass = entity.getClass(); | |
31 | ||
32 | if (!preCollectionChangeMethods.containsKey(entityClass)) { | |
33 | Method[] uniqueDeclaredMethods = ReflectionUtils.getUniqueDeclaredMethods(entityClass); | |
34 | List<Method> methods = Arrays.asList(uniqueDeclaredMethods).stream() | |
35 | .filter(method -> AnnotationUtils.findAnnotation(method, PreCollectionChange.class) != null) | |
36 | .map(method -> { | |
37 | method.setAccessible(true); | |
38 | return method; | |
39 | }) | |
40 | .collect(Collectors.toList()); | |
41 | // Place leaf methods in the end to correspond to constructors order. | |
42 | Collections.reverse(methods); | |
43 | preCollectionChangeMethods.put(entityClass, methods); | |
44 | } | |
45 | ||
46 | List<Method> methods = preCollectionChangeMethods.get(entityClass); | |
47 | for (Method method : methods) { | |
48 | try { | |
49 | method.invoke(entity, (Object[]) null); | |
50 | } catch (IllegalAccessException | InvocationTargetException e) { | |
51 | throw new CallbackException(e); | |
52 | } | |
53 | } | |
54 | } | |
55 | } | |
56 | } | |
57 | ||
58 | ||
59 | ||
60 | @Entity | |
61 | public abstract class Device { | |
62 | ||
63 | @ManyToMany | |
64 | @JoinTable( | |
65 | name = "device_application", | |
66 | joinColumns = { | |
67 | @JoinColumn(name = "device_id"), | |
68 | }, | |
69 | inverseJoinColumns = { | |
70 | @JoinColumn(name = "application_id"), | |
71 | }) | |
72 | private Set<Application> applications = new HashSet<>(); | |
73 | ||
74 | public Set<Application> getApplications() { | |
75 | return applications; | |
76 | } | |
77 | ||
78 | public void setApplications(Set<Application> applications) { | |
79 | this.applications = applications; | |
80 | } | |
81 | ||
82 | @PrePersist | |
83 | private void prePersist() { | |
84 | checkApplications(); | |
85 | } | |
86 | ||
87 | @PreUpdate | |
88 | private void preUpdate() { | |
89 | checkApplications(); | |
90 | } | |
91 | ||
92 | @PreCollectionChange | |
93 | private void checkApplications() { | |
94 | Class<? extends Application> applicationClass = getApplicationClass(); | |
95 | for (Application application : applications) { | |
96 | if (!applicationClass.isAssignableFrom(application.getClass())) { | |
97 | throw new IllegalStateException("All applications must be of class " + applicationClass.getName()); | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | @Transient | |
103 | protected abstract Class<? extends Application> getApplicationClass(); | |
104 | } |