The amount of data collected by applications nowadays is growing at a scary pace. Many of them need to handle billions of users generating and consuming data at an incredible speed. Maybe you are wondering how to create an application like this? What is required? What works best for your project?
In this session we’ll compare popular Java and JVM persistence frameworks for NoSQL databases: Spring Data, Micronaut, Hibernate OGM, Jakarta NoSQL, and GORM. How do they compare, what are the strengths, weaknesses, differences, and similarities? We’ll show each of them with a selection of different NoSQL database systems (Key-Value, Document, Column, Graph).
The data load on applications has increased exponentially in recent years. We know the JVM (Java Virtual Machine) can cope with heavy loads very well yet we often come across the big dilemma: there are tons of persistence frameworks out there but which one performs best for my case? It would normally take ages to evaluate and choose the best fit for your use case. We’ve done those comparisons for you.
5. New digital trends create new technical
challenges
@thodorisbais@wernerkeil @otaviojava
6. • Develop with agility
• Operate at any scale
• Deliver the performance and
availability required to meet the
demands of Digital Economy
businesses
What are the technical challenges?
7. 7
• Handle large volumes of data at high-speed with a scale-out architecture
• Store unstructured, semi-structured, or structured data
• Enable easy updates to schemas and fields
• Developer-friendly
• Take full advantage of the cloud to deliver zero downtime
Advantages of NoSQL
8. Why this talk
Tons of persistence frameworks
Which one performs best for your case?
JVM can cope with heavy loads
Would normally take ages to
compare
26. Entities
@Node("Person")
public class PersonEntity {
@Id
private final String name;
private final Integer born;
}
@Node("Movie")
public class MovieEntity {
@Id
private final String title;
@Property("tagline")
private final String description;
@Relationship(type = "ACTED_IN", direction = INCOMING)
private Map<PersonEntity, Roles> actorsAndRoles =
new HashMap<>();
@Relationship(type = "DIRECTED", direction = INCOMING)
private List<PersonEntity> directors = new ArrayList<>();
}
28. @Document(collection = "gods")
public class God { … }
interface GodRepository extends
MongoRepository<God, String> { … }
What about the Controller?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring.data.mongodb.database=mythology
spring.data.mongodb.port=27017
Logistics Domain
33. Repository with Queries
interface PersonRepository extends Repository<Person, Long> {
@Query("select * from Person")
Optional<Person> findByQuery();
@Query("select * from Person where id = @id")
Optional<Person> findByQuery(@Param("id") String id);
}
34. Diversity
@Entity("god")
public class God {
@Column
private String name;
@UDT("weapon")
@Column
private Weapon weapon;
}
interface GodRepository extends
CassandraRepository<God, String> {
@CQL("select * from God where name = ?")
List<God> findByName(String name);
}
35. List<Movie> movies = documentTemplate.query("select * from Movie
where year > 2012");
List<Person> people = columnTemplate.query("select * from Person
where age = 25");
Optional<God> god = keyValueTemplate.query("get 'Ullr'");
List<City> cities = graphTemplate.query("g.V().hasLabel('City')");
Query by Text
45. Warning
“In most cases, multi-document transaction incurs a greater
performance cost over single document writes, and the availability of
multi-document transactions should not be a replacement for
effective schema design. For many scenarios, the denormalized data
model (embedded documents and arrays) will continue to be optimal
for your data and use cases. That is, for many scenarios, modeling
your data appropriately will minimize the need for multi-document
transactions.”
Documentation
46. Entity
@Entity(name = "book")
@Indexed
@Analyzer(impl = StandardAnalyzer.class)
public class Book {
@Id
@DocumentId
private Long isbn;
@Column
@Field(analyze = Analyze.NO)
private String name;
@Column
@Field
private String author;
@Column
@Field
private String category;
}
47. Operations
EntityManagerFactory managerFactory = Persistence.createEntityManagerFactory("hibernate");
EntityManager manager = managerFactory.createEntityManager();
manager.getTransaction().begin();
Book cleanCode = getBook(1L, "Clean Code", "Robert Cecil Martin");
manager.merge(cleanCode);
manager.getTransaction().commit();
Book book = manager.find(Book.class, 1L);
48. Warning
“Cassandra does not use RDBMS ACID transactions with
rollback or locking mechanisms...
As a non-relational database, Cassandra does not support joins
or foreign keys, and consequently does not offer consistency in
the ACID sense.”
DataStax Documentation
50. Conclusions
Still in Progress ❌
Supports a huge number of NoSQL
database systems
✅
Loosely coupled code makes switching between
different NoSQL vendors just a matter of configuration
✅
Removes boiler-plate code and
provides a cleaner, more readable DAO
✅
51. Conclusions
Switching between different NoSQL
vendors not so easy
❌
Micronaut Data does not support NoSQL
databases yet
❌
Still in Progress ❌
Often faster with a lower footprint and polyglot
language support for Java, Kotlin and Groovy
✅
52. Conclusions
Provides a cleaner and more readable DAO
implementation
✅
Works with Grails, Micronaut or Spring Boot, polyglot
language support for Java and Groovy
✅
Removes a lot of boiler-plate code ✅
Only 3 to 4 of the most popular NoSQL databases are supported
out of the box, others require more effort or won’t work yet ❌
53. Conclusions
Provides a cleaner and more readable DAO
implementation
✅
Loosely coupled code makes switching between
different NoSQL vendors just a matter of configuration
✅
Removes a lot of boiler-plate code ✅
Only half a dozen popular NoSQL databases are supported out of
the box, others require more effort or won’t work yet ❌
54. Conclusions
Using a mapper for all scenarios is not a
recommended approach
❌
Some JPA concepts are not easily mapped to
the NoSQL world (e.g. transactions)
❌
No error-safe way to run the query language and hydrate DTOs
from the result ❌
Outdated, no release since 2018 ❌