Giter Site home page Giter Site logo

orm16's Introduction

About ORM16

ORM16 is a library exploring code generation-based approach to ORM for Java 17 and focusing on records as persistent data model.

Example

Input Java model

package com.example.model;

@Serialized(context = PERSISTENCE, as = "accounts") // generate JDBC mapping
@Serialized(context = INTEGRATION, format = JSON)   // generate JSON mapping
public record Account(@Id UUID uuid,                // primary key
                      Instant created,              // use standard mapping to TIMESTAMP
                      String username,
                      @Value Locale locale,         // serialize as string value
                      @Mapping(                       // unwrap object (only in database)
                              context = PERSISTENCE, 
                              serializeAs = EMBEDDED,
                              overrides = {
                                      @AttributeOverride(map = "currencyCode", to = "currency")
                              }) 
                      @Mapping(context = INTEGRATION, serializeAs = VALUE) // serialize to string e.g. "100 EUR" 
                      Money balance             
                     ) {
}

public record Money(BigDecimal amount,
                    String currencyCode) {
    public static Money fromString(String value) {
        // parse string representation 
    }
    public String toString() {
        // build string representation of this object
    }
}

Database table in PostgreSQL

CREATE TABLE accounts (
    uuid             UUID NOT NULL PRIMARY KEY,  // account.uuid()
    created          TIMESTAMP NOT NULL,         // java.sql.Timestamp.from(account.created())
    username         VARCHAR(64) NOT NULL,       // account.username()
    locale           VARCHAR(5) NOT NULL,        // account.locale().toString()
    balance_amount   NUMERIC(10,2) DEFAULT NULL, // account.balance().amount()
    balance_currency CHAR(3) DEFAULT NULL        // account.balance().currencyCode()
)

JSON model

{
  "uuid"      : "92147655-226e-415e-8976-1844a8367ec6",
  "created"   : "2022-01-01T14:30:23.341Z",
  "username"  : "mustermann", 
  "locale"    : "en-US",
  "balance"   : "200 EUR"
}

Generated code

package com.example.model.jdbc;

public class AccountRepository implements Repository<Account, UUID> {
    
    public AccountRepository(JdbcDatabase jdbc) {
        // Inject connection pool / database wrapper
    }
    
    public void add(Account account) {
        // ...
    }
    
    public void update(Account account) {
        // ...
    }
    
    public Optional<Account> findById(UUID uuid) { 
        // ...
    }
    // other applicable methods
}

Planned v1 features

  1. Zero use of reflection at runtime
  2. Flexible mapping of records with customizable table and column names
  3. Separate mapping for persistence (JDBC/Postgres) and integration (JSON) contexts
  4. Variety of standard Java type mappings (primitives, Java Time API, UUIDs, URLs, enums)
  5. Arbitrary type conversions via factory methods or custom converter classes
  6. Unwrapping embedded entities
  7. Sensible defaults to reduce verbosity
  8. Micronaut microservice demo

Current open questions and challenges

  1. How to inject repository in the user code? ServiceLoader, Guice, Spring?
  2. Custom finders: findByXXX vs Criteria API convention, how to declare interface?
  3. Object tree traversal: how to model foreign keys and corresponding relationships? How to fetch this data?
  4. Plugin architecture: How to support different database dialects?
  5. Caching: does it make sense in microservice architectures? Should it be part of the solution?

orm16's People

Contributors

ivan-gammel avatar

Stargazers

Aniket avatar  avatar

Watchers

 avatar

orm16's Issues

Implement Criteria API prototype

Simple criteria API can be a reasonable alternative to Spring Data-like finder methods, if it enables at least filtering and ordering of the results.
Possible solution may look like following:

Java model

public record Account(String firstName, LocalDate birthDate) {}

Generated code

public class AccountRepository implements Finder<AccountCriteria, Account> {

    public static class AccountCriteria implements Criteria<AccountCriteria, Account> {}

    public static StringCriteriaBuilder<AccountCriteria> firstName() {}
    public static TemporalCriteriaBuilder<AccountCriteria> birthDate() {}

    // restrict to specific types of conditions
   @Override
    public List<Account> findAll(AccountCriteria criteria) {
         var rs = jdbc.query("SELECT firstName, birthDate FROM Account WHERE " + criteria.toSQLTemplate(), criteria.params())
    }
}

User code

AccountRepository accounts;

@Get("/search-accounts")
public List<Accounts> find(LocalDate givenDate, String searchString) {
      return accounts.findAll(birthDate().before(givenDate)
                                           .and(firstName().containsIgnoreCase(searchString)));
}

Implement embedding / conversion model

As first PoC has shown viability of this approach, next step will be to implement the model for embedding entities and data type conversions.
The model must support reasonably deep embedding hierarchies and chaining of custom and built-in conversions, e.g.:

Embedding
Given following structure:

record A(@Embed B b) {}
record B(@Embed C c) {}
record C(@Embed D d) {}
record D(String value) {}

The following table could be mapped:

CREATE TABLE A (
  b_c_d_value VARCHAR(255)
);

Conversion
Given the following record:

record A(@Map(using = MyTimestampToInstant.class) MyTimestamp value) {}

The following table could be mapped, assuming conversion path from MyTimestamp to Instant and further to javax.sql.Timestamp.

CREATE TABLE A (
  value TIMESTAMP NOT NULL
);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.