Logo

dev-resources.site

for different kinds of informations.

Introducing Stalactite ORM

Published at
5/20/2024
Categories
java
orm
jpa
spring
Author
guiommary
Categories
4 categories in total
java
open
orm
open
jpa
open
spring
open
Author
9 person written this
guiommary
open
Introducing Stalactite ORM

Java ORM world is very steady and few libraries exist, but none of them brought any breaking change over the last decade. Meanwhile, application architecture evolved with some trends such as Hexagonal Architecture, CQRS, Domain Driven Design, or Domain Purity. Stalactite tries to be more suitable to these new paradigms by allowing to persist any kind of Class without the need to annotate them or use external XML files: its mapping is made of method reference.

As a benefit, you get a better view of the entity graph since the mapping is made through a fluent API that chains your entity relations, instead of spreading annotations all over entities. This is very helpful to see the complexity of your entity graph, which would impact its load as well as the memory. Moreover, since Stalactite only fetches data eagerly, we can say that what you see is what you get. Here is a very small example:

MappingEase.entityBuilder(Country.class, Long.class)
    .mapKey(Country::getId, IdentifierPolicy.afterInsert())
    .mapOneToOne(Country::getCapital, MappingEase.entityBuilder(City.class, Long.class)
        .mapKey(City::getId, IdentifierPolicy.afterInsert())
        .map(City::getName))
Enter fullscreen mode Exit fullscreen mode

First Steps

The release 2.0.0 is out for some weeks and is available as a Maven dependency, hereafter is an example with HSQLDB. For now, Stalactite is compatible with the following databases (mainly in their latest version): HSQLDB, H2, PostgreSQL, MySQL, and MariaDB.

<dependency>
   <groupId>org.codefilarete.stalactite</groupId>
   <artifactId>orm-hsqldb-adapter</artifactId>
   <version>2.0.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

If you're interested in a less database-vendor-dedicated module, you can use the orm-all-adapter module. Just be aware that it will bring you extra modules and extra JDBC drivers, heaving your artifact.

After getting Statactite as a dependency, the next step is to have a JDBC DataSource and pass it to a org.codefilarete.stalactite.engine.PersistenceContext:

org.hsqldb.jdbc.JDBCDataSource dataSource= new org.hsqldb.jdbc.JDBCDataSource();
dataSource.setUrl("jdbc:hsqldb:mem:test");
dataSource.setUser("sa");
dataSource.setPassword("");
PersistenceContext persistenceContext = new PersistenceContext(dataSource, new HSQLDBDialect());
Enter fullscreen mode Exit fullscreen mode

Then comes the interesting part: the mapping. Supposing you get a Country, you can quickly set up its mapping through the Fluent API, starting with the org.codefilarete.stalactite.mapping.MappingEase class as such:

EntityPersister<Country, Long> countryPersister = MappingEase.entityBuilder(Country.class, Long.class)
    .mapKey(Country::getId, IdentifierPolicy.afterInsert())
    .map(Country::getName)
    .build(persistenceContext);
Enter fullscreen mode Exit fullscreen mode
  • the afterInsert() identifier policy means that the country.id column is an auto-increment one. Two other policies exist: the beforeInsert()for identifier given by a database Sequence (for example), and the alreadyAssigned() for entities that have a natural identifier given by business rules,
  • any non-declared property is considered transient and not managed by Stalactite. The schema can be generated with the org.codefilarete.stalactite.sql.ddl.DDLDeployer class as such (it will generate it into the PersistenceContext dataSource):
DDLDeployer ddlDeployer = new DDLDeployer(persistenceContext);
ddlDeployer.deployDDL();
Enter fullscreen mode Exit fullscreen mode

Finally, you can persist your entities thanks to the EntityPersister obtained previously, please find the example below. You might notice that you won't find JPA methods in Stalactite persister. The reason is that Stalactite is far different from JPA and doesn't aim at being compatible with it: no annotation, no attach/detach mechanism, no first-level cache, no lazy loading, and many more. Hence, the methods are quite straight to their goal:

Country myCountry = new Country();
myCountry.setName("myCountry"); 
countryPersister.insert(myCountry); 
myCountry.setName("myCountry with a different name"); 
countryPersister.update(myCountry); 
Country loadedCountry = countryPersister.select(myCountry.getId()); 
countryPersister.delete(loadedCountry);
Enter fullscreen mode Exit fullscreen mode

Spring Integration

There was a raw usage of Stalactite, meanwhile, you may be interested in its integration with Spring to benefit from the magic of its @Repository. Stalactite provides it, just be aware that it's still a work-in-progress feature. The approach to activate it is the same as for JPA: enable Stalactite repositories thanks to the @EnableStalactiteRepositories annotation on your Spring application. Then you'll declare the PersistenceContext and EntityPersister as @Bean :

@Bean
public PersistenceContext persistenceContext(DataSource dataSource) {
    return new PersistenceContext(dataSource);
}

@Bean
public EntityPersister<Country, Long> countryPersister(PersistenceContext persistenceContext) { 
    return MappingEase.entityBuilder(Country.class, long.class) 
            .mapKey(Country::getId, IdentifierPolicy.afterInsert())
            .map(Country::getName)
            .build(persistenceContext);
}
Enter fullscreen mode Exit fullscreen mode

Then you can declare your repository as such, to be injected into your services :

@Repository
public interface CountryStalactiteRepository extends StalactiteRepository<Country, Long> {
}
Enter fullscreen mode Exit fullscreen mode

As mentioned earlier, since the paradigm of Stalactite is not the same as JPA (no annotation, no attach/detach mechanism, etc), you won't find the same methods of JPA repository in Stalactite ones :

  • save : Saves the given entity, either inserting it or updating it according to its persistence states
  • saveAll : Same as the previous one, with a massive API
  • findById : Try to find an entity by its id in the database
  • findAllById : Same as the previous one, with a massive API
  • delete : Delete the given entity from the database
  • deleteAll : Same as the previous one, with a massive API

Conclusion

In these chapters we introduced the Stalactite ORM, more information about the configuration, the mapping, and all the documentation are available on the website.

The project is open-source with the MIT license and shared through Github.

Thanks for reading, any feedback is appreciated!

jpa Article's
30 articles in total
Favicon
Learn Spring Data JPA, Part - 1
Favicon
Spring Data JPA: Speed Up Development & Business Focus
Favicon
Unidirectional associations for one-to-many
Favicon
Understanding Database Connection Management in Spring Boot with Hibernate and Spring Data JPA
Favicon
Como eu reduzi em até 99% o tempo de resposta da minha API
Favicon
🐾 Hibernate Zoo: Путеводитель по языкам запросов в мире данных 🐾
Favicon
How To Fetch Data By Using DTO Projection In Spring Data JPA
Favicon
Relationships in JPA: Creating Entities Without Dependency
Favicon
Spring Data JPA Stream Query Methods
Favicon
Differences between JpaRepository and CrudRepository and when you need to chose each
Favicon
Understanding JPA Pessimistic Locking vs. Serializable Isolation in Transactions
Favicon
Uma breve introdução ao Hibernate
Favicon
Connecting Spring Boot Applications to a Database with Spring Data JPA
Favicon
Working with Spring Data JPA: CRUD Operations and Beyond
Favicon
The Importance of Using Interfaces for JpaRepository(Java Persistence API) in Spring Data JPA
Favicon
GitHub Mastery: Creating Repositories and Managing PRs with Ease
Favicon
Spring Boot Common Sense: Part 2 Crafting Effective JPA Entities for Robust Data Models
Favicon
Applying JSON Patch to Entity in a Spring Boot Application: A Practical Guide
Favicon
Entendendo @MappedSuperclass em JPA
Favicon
Como iniciar um aplicativo Spring Boot + JPA + MySQL
Favicon
Understanding JPA Mappings in Spring Boot: One-to-One, One-to-Many, Many-to-One, and Many-to-Many Relationships
Favicon
Configurando o Spring com JPA e Microsoft SQL Server
Favicon
Java Hibernate vs JPA: Rapid review for you
Favicon
Database Integration with Spring Boot : Best Practices and Tools
Favicon
what is JPA? explain few configurations
Favicon
Introducing Stalactite ORM
Favicon
How to deal with N+1 problems with Hibernate
Favicon
Jakarta Persistence API (JPA) example application: Northwind sample database
Favicon
spring JPA entities: cheat sheet
Favicon
Java Hibernate vs JPA: Quick Review

Featured ones: