Java中Stalactite ORM简介

快速介绍 Stalactite ORM以及与 Spring 框架的集成:

Java ORM世界非常稳定,存在的库很少,但它们在过去十年中都没有带来任何突破性的变化。同时,应用程序架构随着一些趋势而发展,例如六边形架构、CQRS、领域驱动设计或领域纯度。

Stalactite 试图通过允许持久化任何类型的类而不需要注释它们或使用外部 XML 文件来更适合这些新范例:

  • 它的映射由方法引用组成

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))


这样做的好处是,您可以更好地查看实体图,因为映射是通过流畅的应用程序接口(API)进行的,它将您的实体关系链化,而不是将注释遍布整个实体。

  • 这对了解实体图的复杂性非常有帮助,因为复杂性会影响实体图的负载和内存。
  • 由于 Stalactite 只急切地获取数据,因此我们可以说所见即所得。

第一步
2.0.0 版本已发布几周,并可作为Maven 依赖项使用,以下是 HSQLDB 的示例。目前,Stalactite 兼容以下数据库(主要是最新版本):HSQLDB、H2、PostgreSQL、MySQL 和 MariaDB。

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

如果您对较少数据库供应商专用的模块感兴趣,可以使用 orm-all-adapter 模块。请注意,它会给您带来额外的模块和额外的 JDBC 驱动程序,从而增加您的工件。

将 Statactite 作为依赖项获取后,下一步是获取 JDBC 数据源并将其传递给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());


然后是有趣的部分:映射。假设您获得一个国家/地区,您可以通过 Fluent API 快速设置其映射,从org.codefilarete.stalactite.mapping.MappingEase类开始:

EntityPersister<Country, Long> countryPersister = MappingEase.entityBuilder(Country.class, Long.class)
    .mapKey(Country::getId, IdentifierPolicy.afterInsert())
    .map(Country::getName)
    .build(persistenceContext);

  • afterInsert():标识符策略,意味着country.id列是自增列。还存在另外两种策略:beforeInsert()由数据库序列(例如)给出的标识符,以及alreadyAssigned():具有由业务规则给出的自然标识符的实体,
  • 任何未声明的属性均被视为暂时的,不由Stalactite管理。

表结构模型可以使用org.codefilarete.stalactite.sql.ddl.DDLDeployer类来生成(它将生成到PersistenceContext数据源中):

DDLDeployer ddlDeployer = new DDLDeployer(persistenceContext);
ddlDeployer.deployDDL();


最后,您可以通过EntityPersister之前获得的信息来持久化您的实体,请参阅下面的示例。

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);


您可能会注意到,在 Stalactite persister 中找不到JPA方法。原因是Stalactite与JPA有很大不同,并且不以兼容JPA为目标:

  • 没有注释,
  • 没有附加/分离机制,
  • 没有一级缓存,
  • 没有延迟加载等等。

因此,这些方法非常直接地达到了他们的目标:


与 Spring 集成
你可能会对Stalactite的原始用法感兴趣,同时,你可能会对它与 Spring 的集成感兴趣,以便从 @Repository 的神奇功能中获益。

Stalactite提供了这一功能,但需要注意的是,它仍是一个正在开发中的功能。

激活它的方法与 JPA 相同:

  • 在 Spring 应用程序中使用 @EnableStalactiteRepositories 注解来启用Stalactite存储库。
  • 然后将 PersistenceContext 和 EntityPersister 声明为 @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);
}


然后,您就可以将您的版本库声明为这样的版本库,以便注入到您的服务中:

@Repository
public interface CountryStalactiteRepository extends StalactiteRepository<Country, Long> {
}

如前所述,由于 Stalactite 的范式与 JPA 不同(没有注解、没有附加/脱离机制等),因此在 Stalactite 中找不到与 JPA 存储库相同的方法:

  • save:保存给定实体,根据其持久化状态插入或更新实体
  • saveAll:与前一个方法相同,但有一个庞大的应用程序接口
  • findById:尝试在数据库中按 ID 查找实体
  • findAllById:与前一种方法相同,提供大量应用程序接口
  • delete:从数据库中删除给定实体
  • deleteAll:与前一个相同,使用大量 API

结论
在这些章节中,我们介绍了 Stalactite ORM,有关配置、映射和所有文档的更多信息可以在网站上找到。 
该项目是开源的,拥有 MIT 许可证,并通过Github共享。