You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: modules/ROOT/pages/auditing.adoc
-8Lines changed: 0 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,6 @@ Applications that only track creation and modification dates are not required do
17
17
We provide `@CreatedBy` and `@LastModifiedBy` to capture the user who created or modified the entity as well as `@CreatedDate` and `@LastModifiedDate` to capture when the change happened.
18
18
19
19
.An audited entity
20
-
====
21
20
[source,java]
22
21
----
23
22
class Customer {
@@ -31,15 +30,13 @@ class Customer {
31
30
// … further properties omitted
32
31
}
33
32
----
34
-
====
35
33
36
34
As you can see, the annotations can be applied selectively, depending on which information you want to capture.
37
35
The annotations, indicating to capture when changes are made, can be used on properties of type JDK8 date and time types, `long`, `Long`, and legacy Java `Date` and `Calendar`.
38
36
39
37
Auditing metadata does not necessarily need to live in the root level entity but can be added to an embedded one (depending on the actual store in use), as shown in the snippet below.
40
38
41
39
.Audit metadata in embedded entity
42
-
====
43
40
[source,java]
44
41
----
45
42
class Customer {
@@ -59,7 +56,6 @@ class AuditMetadata {
59
56
60
57
}
61
58
----
62
-
====
63
59
64
60
[[auditing.interfaces]]
65
61
=== Interface-based Auditing Metadata
@@ -73,7 +69,6 @@ In case you use either `@CreatedBy` or `@LastModifiedBy`, the auditing infrastru
73
69
The following example shows an implementation of the interface that uses Spring Security's `Authentication` object:
74
70
75
71
.Implementation of `AuditorAware` based on Spring Security
76
-
====
77
72
[source, java]
78
73
----
79
74
class SpringSecurityAuditorAware implements AuditorAware<User> {
@@ -89,7 +84,6 @@ class SpringSecurityAuditorAware implements AuditorAware<User> {
89
84
}
90
85
}
91
86
----
92
-
====
93
87
94
88
The implementation accesses the `Authentication` object provided by Spring Security and looks up the custom `UserDetails` instance that you have created in your `UserDetailsService` implementation. We assume here that you are exposing the domain user through the `UserDetails` implementation but that, based on the `Authentication` found, you could also look it up from anywhere.
95
89
@@ -102,7 +96,6 @@ We provide an `ReactiveAuditorAware<T>` SPI interface that you have to implement
102
96
The following example shows an implementation of the interface that uses reactive Spring Security's `Authentication` object:
103
97
104
98
.Implementation of `ReactiveAuditorAware` based on Spring Security
105
-
====
106
99
[source, java]
107
100
----
108
101
class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {
@@ -118,6 +111,5 @@ class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {
118
111
}
119
112
}
120
113
----
121
-
====
122
114
123
115
The implementation accesses the `Authentication` object provided by Spring Security and looks up the custom `UserDetails` instance that you have created in your `UserDetailsService` implementation. We assume here that you are exposing the domain user through the `UserDetails` implementation but that, based on the `Authentication` found, you could also look it up from anywhere.
Copy file name to clipboardExpand all lines: modules/ROOT/pages/dependencies.adoc
-4Lines changed: 0 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,6 @@
4
4
Due to the different inception dates of individual Spring Data modules, most of them carry different major and minor version numbers. The easiest way to find compatible ones is to rely on the Spring Data Release Train BOM that we ship with the compatible versions defined. In a Maven project, you would declare this dependency in the `<dependencyManagement />` section of your POM as follows:
5
5
6
6
.Using the Spring Data release train BOM
7
-
====
8
7
[source, xml, subs="+attributes"]
9
8
----
10
9
<dependencyManagement>
@@ -19,7 +18,6 @@ Due to the different inception dates of individual Spring Data modules, most of
19
18
</dependencies>
20
19
</dependencyManagement>
21
20
----
22
-
====
23
21
24
22
[[dependencies.train-names]]
25
23
[[dependencies.train-version]]
@@ -33,7 +31,6 @@ The version name follows `+${calver}+` for GA releases and service releases and
33
31
You can find a working example of using the BOMs in our https://github.com/spring-projects/spring-data-examples/tree/main/bom[Spring Data examples repository]. With that in place, you can declare the Spring Data modules you would like to use without a version in the `<dependencies />` block, as follows:
34
32
35
33
.Declaring a dependency to a Spring Data module
36
-
====
37
34
[source, xml]
38
35
----
39
36
<dependencies>
@@ -43,7 +40,6 @@ You can find a working example of using the BOMs in our https://github.com/sprin
Copy file name to clipboardExpand all lines: modules/ROOT/pages/entity-callbacks.adoc
-8Lines changed: 0 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,6 @@ An `EntityCallback` is directly associated with its domain type through its gene
24
24
Each Spring Data module typically ships with a set of predefined `EntityCallback` interfaces covering the entity lifecycle.
25
25
26
26
.Anatomy of an `EntityCallback`
27
-
====
28
27
[source,java]
29
28
----
30
29
@FunctionalInterface
@@ -44,10 +43,8 @@ public interface BeforeSaveCallback<T> extends EntityCallback<T> {
44
43
<1> `BeforeSaveCallback` specific method to be called before an entity is saved. Returns a potentially modifed instance.
45
44
<2> The entity right before persisting.
46
45
<3> A number of store specific arguments like the _collection_ the entity is persisted to.
47
-
====
48
46
49
47
.Anatomy of a reactive `EntityCallback`
50
-
====
51
48
[source,java]
52
49
----
53
50
@FunctionalInterface
@@ -67,14 +64,12 @@ public interface ReactiveBeforeSaveCallback<T> extends EntityCallback<T> {
67
64
<1> `BeforeSaveCallback` specific method to be called on subscription, before an entity is saved. Emits a potentially modifed instance.
68
65
<2> The entity right before persisting.
69
66
<3> A number of store specific arguments like the _collection_ the entity is persisted to.
70
-
====
71
67
72
68
NOTE: Optional entity callback parameters are defined by the implementing Spring Data module and inferred from call site of `EntityCallback.callback()`.
73
69
74
70
Implement the interface suiting your application needs like shown in the example below:
75
71
76
72
.Example `BeforeSaveCallback`
77
-
====
78
73
[source,java]
79
74
----
80
75
class DefaultingEntityCallback implements BeforeSaveCallback<Person>, Ordered { <2>
@@ -97,7 +92,6 @@ class DefaultingEntityCallback implements BeforeSaveCallback<Person>, Ordered {
97
92
----
98
93
<1> Callback implementation according to your requirements.
99
94
<2> Potentially order the entity callback if multiple ones for the same domain type exist. Ordering follows lowest precedence.
100
-
====
101
95
102
96
[[entity-callbacks.register]]
103
97
== Registering Entity Callbacks
@@ -108,7 +102,6 @@ Most template APIs already implement `ApplicationContextAware` and therefore hav
108
102
The following example explains a collection of valid entity callback registrations:
109
103
110
104
.Example `EntityCallback` Bean registration
111
-
====
112
105
[source,java]
113
106
----
114
107
@Order(1) <1>
@@ -164,4 +157,3 @@ class UserCallbacks implements BeforeConvertCallback<User>,
164
157
<2> `BeforeSaveCallback` receiving its order via the `Ordered` interface implementation.
165
158
<3> `BeforeSaveCallback` using a lambda expression. Unordered by default and invoked last. Note that callbacks implemented by a lambda expression do not expose typing information hence invoking these with a non-assignable entity affects the callback throughput. Use a `class` or `enum` to enable type filtering for the callback bean.
166
159
<4> Combine multiple entity callback interfaces in a single implementation class.
Copy file name to clipboardExpand all lines: modules/ROOT/pages/kotlin-coroutines.adoc
-4Lines changed: 0 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,6 @@ Spring Data modules provide support for Coroutines on the following scope:
14
14
Coroutines support is enabled when `kotlinx-coroutines-core`, `kotlinx-coroutines-reactive` and `kotlinx-coroutines-reactor` dependencies are in the classpath:
15
15
16
16
.Dependencies to add in Maven pom.xml
17
-
====
18
17
[source,xml]
19
18
----
20
19
<dependency>
@@ -32,7 +31,6 @@ Coroutines support is enabled when `kotlinx-coroutines-core`, `kotlinx-coroutine
Copy file name to clipboardExpand all lines: modules/ROOT/pages/object-mapping.adoc
-20Lines changed: 0 additions & 20 deletions
Original file line number
Diff line number
Diff line change
@@ -113,7 +113,6 @@ class Person {
113
113
----
114
114
115
115
.A generated Property Accessor
116
-
====
117
116
[source, java]
118
117
----
119
118
class PersonPropertyAccessor implements PersistentPropertyAccessor {
@@ -140,7 +139,6 @@ class PersonPropertyAccessor implements PersistentPropertyAccessor {
140
139
<2> By default, Spring Data uses field-access to read and write property values. As per visibility rules of `private` fields, `MethodHandles` are used to interact with fields.
141
140
<3> The class exposes a `withId(…)` method that's used to set the identifier, e.g. when an instance is inserted into the datastore and an identifier has been generated. Calling `withId(…)` creates a new `Person` object. All subsequent mutations will take place in the new instance leaving the previous untouched.
142
141
<4> Using property-access allows direct method invocations without using `MethodHandles`.
143
-
====
144
142
145
143
This gives us a roundabout 25% performance boost over reflection.
146
144
For the domain class to be eligible for such optimization, it needs to adhere to a set of constraints:
@@ -156,7 +154,6 @@ By default, Spring Data attempts to use generated property accessors and falls b
156
154
Let's have a look at the following entity:
157
155
158
156
.A sample entity
159
-
====
160
157
[source, java]
161
158
----
162
159
class Person {
@@ -193,7 +190,6 @@ class Person {
193
190
}
194
191
}
195
192
----
196
-
====
197
193
<1> The identifier property is final but set to `null` in the constructor.
198
194
The class exposes a `withId(…)` method that's used to set the identifier, e.g. when an instance is inserted into the datastore and an identifier has been generated.
199
195
The original `Person` instance stays unchanged as a new one is created.
@@ -230,7 +226,6 @@ It's an established pattern to rather use static factory methods to expose these
230
226
Java's allows a flexible design of domain classes where a subclass could define a property that is already declared with the same name in its superclass.
231
227
Consider the following example:
232
228
233
-
====
234
229
[source,java]
235
230
----
236
231
public class SuperType {
@@ -272,7 +267,6 @@ public class SubType extends SuperType {
272
267
}
273
268
}
274
269
----
275
-
====
276
270
277
271
Both classes define a `field` using assignable types. `SubType` however shadows `SuperType.field`.
278
272
Depending on the class design, using the constructor could be the only default approach to set `SuperType.field`.
@@ -315,16 +309,13 @@ Other constructors will be ignored.
315
309
316
310
Consider the following `data` class `Person`:
317
311
318
-
====
319
312
[source,kotlin]
320
313
----
321
314
data class Person(val id: String, val name: String)
322
315
----
323
-
====
324
316
325
317
The class above compiles to a typical class with an explicit constructor.We can customize this class by adding another constructor and annotate it with `@PersistenceCreator` to indicate a constructor preference:
326
318
327
-
====
328
319
[source,kotlin]
329
320
----
330
321
data class Person(var id: String, val name: String) {
@@ -333,17 +324,14 @@ data class Person(var id: String, val name: String) {
333
324
constructor(id: String) : this(id, "unknown")
334
325
}
335
326
----
336
-
====
337
327
338
328
Kotlin supports parameter optionality by allowing default values to be used if a parameter is not provided.
339
329
When Spring Data detects a constructor with parameter defaulting, then it leaves these parameters absent if the data store does not provide a value (or simply returns `null`) so Kotlin can apply parameter defaulting.Consider the following class that applies parameter defaulting for `name`
340
330
341
-
====
342
331
[source,kotlin]
343
332
----
344
333
data class Person(var id: String, val name: String = "unknown")
345
334
----
346
-
====
347
335
348
336
Every time the `name` parameter is either not part of the result or its value is `null`, then the `name` defaults to `unknown`.
349
337
@@ -353,12 +341,10 @@ Every time the `name` parameter is either not part of the result or its value is
353
341
In Kotlin, all classes are immutable by default and require explicit property declarations to define mutable properties.
354
342
Consider the following `data` class `Person`:
355
343
356
-
====
357
344
[source,kotlin]
358
345
----
359
346
data class Person(val id: String, val name: String)
360
347
----
361
-
====
362
348
363
349
This class is effectively immutable.
364
350
It allows creating new instances as Kotlin generates a `copy(…)` method that creates new object instances copying all property values from the existing object and applying property values provided as arguments to the method.
@@ -368,7 +354,6 @@ It allows creating new instances as Kotlin generates a `copy(…)` method that c
368
354
369
355
Kotlin allows declaring https://kotlinlang.org/docs/inheritance.html#overriding-properties[property overrides] to alter properties in subclasses.
370
356
371
-
====
372
357
[source,kotlin]
373
358
----
374
359
open class SuperType(open var field: Int)
@@ -377,13 +362,11 @@ class SubType(override var field: Int = 1) :
377
362
SuperType(field) {
378
363
}
379
364
----
380
-
====
381
365
382
366
Such an arrangement renders two properties with the name `field`.
383
367
Kotlin generates property accessors (getters and setters) for each property in each class.
384
368
Effectively, the code looks like as follows:
385
369
386
-
====
387
370
[source,java]
388
371
----
389
372
public class SuperType {
@@ -421,7 +404,6 @@ public final class SubType extends SuperType {
421
404
}
422
405
}
423
406
----
424
-
====
425
407
426
408
Getters and setters on `SubType` set only `SubType.field` and not `SuperType.field`.
427
409
In such an arrangement, using the constructor is the only default approach to set `SuperType.field`.
@@ -446,7 +428,6 @@ Spring Data can read and write types that define properties using Value Classes.
446
428
447
429
Consider the following domain model:
448
430
449
-
====
450
431
[source,kotlin]
451
432
----
452
433
@JvmInline
@@ -457,7 +438,6 @@ data class Contact(val id: String, val name:String, val emailAddress: EmailAddre
457
438
458
439
<1> A simple value class with a non-nullable value type.
459
440
<2> Data class defining a property using the `EmailAddress` value class.
460
-
====
461
441
462
442
NOTE: Non-nullable properties using non-primitive value types are flattened in the compiled class to the value type.
463
443
Nullable primitive value types or nullable value-in-value types are represented with their wrapper type and that affects how value types are represented in the database.
0 commit comments