Skip to content

Commit 0e80868

Browse files
Merge pull request #219 from xdev-software/micro-migration-for-developer
Micro migration for developer
2 parents 851ddbf + 6db8d8c commit 0e80868

File tree

44 files changed

+1345
-31
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1345
-31
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# 2.4.2
22

33
* Updated org.springframework.boot.version to v3.4.1
4+
* Added support for the [micro-migration-Framework](https://github.com/xdev-software/micro-migration)
45

56
# 2.4.1
67

docs/modules/ROOT/nav.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
** xref:features/queries.adoc[Queries]
99
** xref:features/transactions.adoc[Transactions]
1010
** xref:features/versions.adoc[Versions]
11+
** xref:features/versioned-migration.adoc[Versioned Migration]
1112
** xref:features/rest-api.adoc[REST Interface]
1213
** xref:features/validation-constraints.adoc[Validation Constraints]
13-
* xref:migration.adoc[Migration from JPA]
14+
* xref:migration-from-jpa.adoc[Migration from JPA]
1415
* xref:known-issues.adoc[Known issues]

docs/modules/ROOT/pages/features/features.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
* xref:features/queries.adoc[Queries]
66
* xref:features/transactions.adoc[Transactions]
77
* xref:features/versions.adoc[Versions]
8+
* xref:features/versioned-migration.adoc[Versioned Migration]
89
* xref:features/rest-api.adoc[REST Interface]
910
* xref:features/validation-constraints.adoc[Validation Constraints]
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
= Versioned Migration
2+
3+
To keep the data in the store up-to-date, {product-name} utilizes https://github.com/xdev-software/micro-migration[XDEV's Micro-Migration].
4+
This means the user can use versioning for the stored data and only apply changes for certain versions of data.
5+
This can be very useful specifically with build-pipelines. https://github.com/xdev-software/micro-migration#intro[More info at Micro-Migration...]
6+
7+
== Implementation
8+
9+
This can be easily achieved by either of these 3 methods:
10+
11+
=== 1. Reflective Scripts
12+
13+
Simply implement a new component with a specific pattern of naming, that extends the ``ReflectiveDataMigrationScript``.
14+
15+
[source,java,title="https://github.com/xdev-software/spring-data-eclipse-store/blob/develop/spring-data-eclipse-store-demo/src/main/java/software/xdev/spring/data/eclipse/store/demo/complex/migration/v1_0_0_Init.java[Reflective example from complex demo]"]
16+
----
17+
package software.xdev.spring.data.eclipse.store.demo.complex.migration;
18+
19+
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.stereotype.Component;
21+
//...
22+
import software.xdev.spring.data.eclipse.store.repository.root.data.version.ReflectiveDataMigrationScript;
23+
24+
@Component
25+
public class v1_0_0_Init extends ReflectiveDataMigrationScript
26+
{
27+
private final OwnerService service;
28+
29+
@Autowired
30+
public v1_0_0_Init(final OwnerService service)
31+
{
32+
this.service = service;
33+
}
34+
35+
@Override
36+
public void migrate(final Context<VersionedRoot, MigrationEmbeddedStorageManager> context)
37+
{
38+
this.service.createNewOwnerAndVisit("Mick", "Fleetwood", "Isabella");
39+
}
40+
}
41+
----
42+
43+
Here the version number on which the data is updated on execution is derived from the class name.
44+
45+
The ``MigrationVersion`` is stored in the root object in the data store.
46+
Therefore, the storage always knows on which version the current data is and the ``DataMigrater`` will only execute the newer scripts.
47+
48+
The scripts are automatically registered by declaring them as ``@Component``s.
49+
That means that they can be anywhere as long as they are discovered by Spring as a component.
50+
51+
=== 2. Custom Scripts
52+
53+
Implementing a script without special naming is possible by implementing the
54+
``DataMigrationScript``.
55+
56+
[source,java,title="https://github.com/xdev-software/spring-data-eclipse-store/blob/develop/spring-data-eclipse-store-demo/src/main/java/software/xdev/spring/data/eclipse/store/demo/complex/migration/CustomNameScript.java[Custom script example from complex demo]"]
57+
----
58+
package software.xdev.spring.data.eclipse.store.demo.complex.migration;
59+
60+
import org.springframework.beans.factory.annotation.Autowired;
61+
import org.springframework.stereotype.Component;
62+
//...
63+
import software.xdev.spring.data.eclipse.store.repository.root.data.version.DataMigrationScript;
64+
65+
@Component
66+
public class CustomNameScriptAddOwner implements DataMigrationScript
67+
{
68+
private final OwnerService service;
69+
70+
public CustomNameScriptAddOwner(@Autowired final OwnerService service)
71+
{
72+
this.service = service;
73+
}
74+
75+
@Override
76+
public MigrationVersion getTargetVersion()
77+
{
78+
return new MigrationVersion(1, 1, 0);
79+
}
80+
81+
@Override
82+
public void migrate(final Context<VersionedRoot, MigrationEmbeddedStorageManager> context)
83+
{
84+
this.service.createNewOwnerAndVisit("John", "McVie", "Ivan");
85+
}
86+
}
87+
----
88+
89+
The version number must be returned explicitly in the ``#getTargetVersion``-method.
90+
91+
=== 3. Custom Migrater
92+
93+
If more customization is needed it is also possible to replace the ``DataMigrater`` completely and implement your own ``MicroMigrater``.
94+
This should only be used if necessary since it adds a lot of complexity to the code.
95+
96+
[source,java,title="https://github.com/xdev-software/spring-data-eclipse-store/blob/develop/spring-data-eclipse-store/src/test/java/software/xdev/spring/data/eclipse/store/integration/isolated/tests/data/migration/with/migrater/CustomMigrater.java[Custom migrater from tests]"]
97+
----
98+
package software.xdev.spring.data.eclipse.store.integration.isolated.tests.data.migration.with.migrater;
99+
100+
import org.springframework.beans.factory.annotation.Autowired;
101+
import org.springframework.stereotype.Component;
102+
import software.xdev.micromigration.migrater.ExplicitMigrater;
103+
import software.xdev.micromigration.migrater.MicroMigrater;
104+
//...
105+
106+
@Component
107+
public class CustomMigrater implements MicroMigrater
108+
{
109+
private final ExplicitMigrater explicitMigrater;
110+
111+
@Autowired
112+
public CustomMigrater(final PersistedEntityRepository repository)
113+
{
114+
this.explicitMigrater = new ExplicitMigrater(new v1_0_0_Init(repository));
115+
}
116+
----

spring-data-eclipse-store-demo/src/main/java/software/xdev/spring/data/eclipse/store/demo/complex/ComplexDemoApplication.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,7 @@ public void run(final String... args)
5555
*/
5656
private void ownerCalls()
5757
{
58-
this.ownerService.logOwners();
59-
this.ownerService.deleteAll();
60-
this.ownerService.logOwners();
61-
this.ownerService.createNewOwnerAndVisit();
58+
this.ownerService.createNewOwnerAndVisit("Stevie", "Nicks", "Peter");
6259
this.ownerService.logOwnersAndVisits();
6360
}
6461

spring-data-eclipse-store-demo/src/main/java/software/xdev/spring/data/eclipse/store/demo/complex/OwnerService.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,16 @@ public void logOwnersAndVisits()
8888
/**
8989
* Transactional
9090
*/
91-
public void createNewOwnerAndVisit()
91+
public void createNewOwnerAndVisit(final String ownerFirstName, final String ownerLastName, final String petName)
9292
{
9393
new TransactionTemplate(this.transactionManager).execute(
9494
status ->
9595
{
96-
final Owner owner = this.createOwner();
96+
final Owner owner = this.createOwner(ownerFirstName, ownerLastName, petName);
9797
this.ownerRepository.save(owner);
9898

9999
final Visit visit = this.createVisit();
100-
owner.addVisit("Peter", visit);
100+
owner.addVisit(petName, visit);
101101
this.ownerRepository.save(owner);
102102
LOG.info("----Stored new owner and visit----");
103103
return null;
@@ -113,14 +113,14 @@ private Visit createVisit()
113113
}
114114

115115
@SuppressWarnings("checkstyle:MagicNumber")
116-
private Owner createOwner()
116+
private Owner createOwner(final String ownerFirstName, final String ownerLastName, final String petName)
117117
{
118118
final Owner owner = new Owner();
119-
owner.setFirstName("Stevie");
120-
owner.setLastName("Nicks");
119+
owner.setFirstName(ownerFirstName);
120+
owner.setLastName(ownerLastName);
121121
final Pet pet = new Pet();
122122
pet.setBirthDate(LocalDate.now().minusWeeks(6));
123-
pet.setName("Peter");
123+
pet.setName(petName);
124124
final PetType petType = new PetType();
125125
petType.setName("Dog");
126126
pet.setType(petType);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright © 2024 XDEV Software (https://xdev.software)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package software.xdev.spring.data.eclipse.store.demo.complex.migration;
17+
18+
import org.springframework.beans.factory.annotation.Autowired;
19+
import org.springframework.stereotype.Component;
20+
21+
import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager;
22+
import software.xdev.micromigration.scripts.Context;
23+
import software.xdev.micromigration.version.MigrationVersion;
24+
import software.xdev.spring.data.eclipse.store.demo.complex.OwnerService;
25+
import software.xdev.spring.data.eclipse.store.repository.root.VersionedRoot;
26+
import software.xdev.spring.data.eclipse.store.repository.root.data.version.DataMigrationScript;
27+
28+
29+
/**
30+
* This is automatically called by the
31+
* {@link software.xdev.spring.data.eclipse.store.repository.root.data.version.DataMigrater} through dependency
32+
* injection.
33+
* <p>
34+
* In contrast to {@link v1_0_0_Init} the version of this script is defined in the method {@link #getTargetVersion()}.
35+
*/
36+
@Component
37+
public class CustomNameScript implements DataMigrationScript
38+
{
39+
private final OwnerService service;
40+
41+
public CustomNameScript(@Autowired final OwnerService service)
42+
{
43+
this.service = service;
44+
}
45+
46+
@Override
47+
public MigrationVersion getTargetVersion()
48+
{
49+
return new MigrationVersion(1, 1, 0);
50+
}
51+
52+
@Override
53+
public void migrate(final Context<VersionedRoot, MigrationEmbeddedStorageManager> context)
54+
{
55+
this.service.createNewOwnerAndVisit("John", "McVie", "Ivan");
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright © 2024 XDEV Software (https://xdev.software)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package software.xdev.spring.data.eclipse.store.demo.complex.migration;
17+
18+
import org.springframework.beans.factory.annotation.Autowired;
19+
import org.springframework.stereotype.Component;
20+
21+
import software.xdev.micromigration.eclipsestore.MigrationEmbeddedStorageManager;
22+
import software.xdev.micromigration.scripts.Context;
23+
import software.xdev.spring.data.eclipse.store.demo.complex.OwnerService;
24+
import software.xdev.spring.data.eclipse.store.repository.root.VersionedRoot;
25+
import software.xdev.spring.data.eclipse.store.repository.root.data.version.ReflectiveDataMigrationScript;
26+
27+
28+
/**
29+
* This is automatically called by the
30+
* {@link software.xdev.spring.data.eclipse.store.repository.root.data.version.DataMigrater} through dependency
31+
* injection.
32+
* <p>
33+
* In contrast to {@link CustomNameScript} the version of this script is defined by
34+
* <b>the name of the class defines the version</b>.
35+
*/
36+
@SuppressWarnings("checkstyle:TypeName")
37+
@Component
38+
public class v1_0_0_Init extends ReflectiveDataMigrationScript
39+
{
40+
private final OwnerService service;
41+
42+
@Autowired
43+
public v1_0_0_Init(final OwnerService service)
44+
{
45+
this.service = service;
46+
}
47+
48+
@Override
49+
public void migrate(final Context<VersionedRoot, MigrationEmbeddedStorageManager> context)
50+
{
51+
this.service.createNewOwnerAndVisit("Mick", "Fleetwood", "Isabella");
52+
}
53+
}

spring-data-eclipse-store/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
<jakarta.el-api.version>6.0.1</jakarta.el-api.version>
5959
<expressly.version>6.0.0-M1</expressly.version>
6060
<hibernate-core.version>6.6.4.Final</hibernate-core.version>
61+
<micro-migration.version>3.0.1</micro-migration.version>
6162
</properties>
6263

6364
<repositories>
@@ -156,7 +157,7 @@
156157
<dependency>
157158
<groupId>software.xdev</groupId>
158159
<artifactId>micro-migration</artifactId>
159-
<version>2.0.0</version>
160+
<version>${micro-migration.version}</version>
160161
<exclusions>
161162
<exclusion>
162163
<artifactId>storage-embedded</artifactId>

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
import software.xdev.spring.data.eclipse.store.repository.config.EclipseStoreClientConfiguration;
4040
import software.xdev.spring.data.eclipse.store.repository.config.EclipseStoreStorageFoundationProvider;
4141
import software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreRepository;
42+
import software.xdev.spring.data.eclipse.store.repository.root.EclipseStoreMigrator;
4243
import software.xdev.spring.data.eclipse.store.repository.root.VersionedRoot;
44+
import software.xdev.spring.data.eclipse.store.repository.root.data.version.DataVersion;
4345
import software.xdev.spring.data.eclipse.store.repository.root.v2_4.EntityData;
4446
import software.xdev.spring.data.eclipse.store.repository.support.SimpleEclipseStoreRepository;
4547
import software.xdev.spring.data.eclipse.store.repository.support.concurrency.ReadWriteLock;
@@ -92,7 +94,7 @@ public EclipseStoreStorage(final EclipseStoreClientConfiguration storeConfigurat
9294
this.classLoaderProvider = storeConfiguration.getClassLoaderProvider();
9395
}
9496

95-
public StorageManager getInstanceOfStorageManager()
97+
public EmbeddedStorageManager getInstanceOfStorageManager()
9698
{
9799
this.ensureEntitiesInRoot();
98100
return this.storageManager;
@@ -120,7 +122,7 @@ private synchronized void ensureEntitiesInRoot()
120122
this.root.getCurrentRootData().getEntityTypesCount(),
121123
this.root.getCurrentRootData().getEntityCount()
122124
);
123-
EclipseStoreMigrator.migrate(this.root, this.storageManager);
125+
EclipseStoreMigrator.migrateStructure(this.root, this.storageManager);
124126
}
125127
}
126128

@@ -492,6 +494,11 @@ public Object getObject(final long objectId)
492494
return this.storageManager.getObject(objectId);
493495
}
494496

497+
public DataVersion getDataVersion()
498+
{
499+
return this.getRoot().getDataVersion();
500+
}
501+
495502
@Override
496503
public ReadWriteLock getReadWriteLock()
497504
{

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/Root.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323

2424
/**
25-
* This is the root object for all versions <2.0.0 and is used for upgrading to the new root.
26-
* @deprecated should not be initialised any more. Version for <2.0.0
25+
* This is the root object for all versions {@literal <}2.0.0 and is used for upgrading to the new root.
26+
* @deprecated should not be initialised any more. Version for {@literal <}2.0.0
2727
*/
2828
@Deprecated(forRemoval = false, since = "2.0.0")
2929
public class Root

0 commit comments

Comments
 (0)