Neues von Spring Data

Someone dragged me in here.

What is Spring Data?

Old new or new new?

Not new

Ingalls: (1.11.x)

still gets bug fixes.

Used by Spring Boot 1.5.x

Somewhat new

Kay: (2.0.x)

1st GA Oct. 2017

current: SR6

Used by Spring Boot 2.0 (Feb. 2018)

Super new

Lovelace: (2.1.x)

current: M2

ETA: September 2018

Kay

Upgrade to Java 8.

  • Java 8 is required.

  • Use of new language features (Lambdas).

  • Use of new classes

    • Optional.

    • java.time API.

    • Stream API.

Pet Peeve

You don’t want to use LocalDateTime.

You want to use Instant instead.

CrudRepository

interface CrudRepository<T, ID> extends Repository<T, ID> {
    S save(S entity);
    Iterable<S> saveAll(Iterable<S> entities)
    Optional<T> findById(ID id);
    boolean existsById(ID id);
    Iterable<T> findAllById(Iterable<ID> ids);
    void deleteById(ID id);
    void delete(T entity);
    void deleteAll(Iterable<? extends T> entities);
}

Tooling support for null-safety

@NonNullApi

@Nullable

Java 9 compatibility.

  • Spring Data works with Java 9.

  • No module descriptors yet.

  • You might need --add-modules java.xml.bind

  • Building Spring Data still requires --permit-illegal-access

Support composable repositories.

interface MyRepository
    extends CrudRepository,
            ARepo, BRepo {...}

class ARepoImpl implements ARepo {...}
class BRepoImpl implements BRepo {...}

MongoOperations

Query query =
  new BasicQuery(new Document());

List<SWCharacter> all =
  ops.find(
    query,
    SWCharacter.class,
    "star-wars"
  );

FluentMongoOperations

List<SWCharacter> all = ops
  .find(SWCharacter.class)
  .inCollection("star-wars")
  .all();

Upgrade to Spring Framework 5.

The important part is the reactive support

Reactive Support

Reactive What?

In a nutshell, reactive programming is about non-blocking, event-driven applications that scale with a small number of threads with back pressure as a key ingredient that aims to ensure producers to not overwhelm consumers.

— Rossen Stoyanchev

The main goal of Reactive Streams is to govern the exchange of stream data across an asynchronous boundary — think passing elements on to another thread or thread-pool — while ensuring that the receiving side is not forced to buffer arbitrary amounts of data.

— Reactive Streams

Reactive Who?

  • MongoDB

  • Redis

  • Couchbase

  • Apache Cassandra

Reactive How?

  • @EnableReactive???Repositories

  • extend ReactiveCrudRepository

  • declare methods using Flux, Mono

Reactive Use

@GetMapping("/people")
Flux<String> namesByLastname(
  @RequestParam Mono<String> lastname) {

  Flux<Person> result =
    repository.findByLastname(lastname);

  return result
    .map(it -> it.getFullName());
}

Lovelace

Mongo DB ChangeStreams

Aggregation filter =
  newAggregation(
    User.class,
    match(where("age").gte(38));

Flux<ChangeStreamEvent<User>> flux =
  reactiveTemplate.changeStream(
    filter,
    User.class,
    ChangeStreamOptions.empty());

Mongo DB Transactions

Requires

  • driver 3.8.0-beta1

  • server 3.7.5

  • Server part of a replica set (size 1 is ok)

Spring Transaction Manager

@Bean
MongoTransactionManager transactionManager(
        MongoDbFactory dbFactory
) {
    return new MongoTransactionManager(dbFactory);
}

Alternatives

  • API for full manual control.

  • API for manually tying to a PlatformTransactionManager

Neo4J

No need for Default Constructors

Neo4J Auditing Support

  • @CreatedDate

  • @CreatedBy,

  • @LastModifiedDate

  • @LastModifiedBy

Spring Data JDBC

Spring Data JDBC

If you are not embarrassed by the first version of your product, you’ve launched too late.

— Reid Hoffman

Why?

Constraints

  • No Proxies (for Entities)

  • No Lazy Loading

  • No Dirty checking

  • Easy is better

@Query support

@Query("SELECT * FROM Person
    WHERE name  < :upper and name > :lower")
List<Person> findByNamedRange(
    @Param("lower") String lower,
    @Param("upper") String upper
);

@Query + Modifying

@Modifying
@Query("DELETE FROM Person WHERE name = :name")
boolean deleteByName(@Param("name") String name);

CRUD support

very, very limited

CRUD with References

  • remove all formerly referenced Aggregate Members

  • update the Aggregate Root

  • add referenced Aggregate Members

Aggregate Root

  • Everything you reference is part of the aggregate.

  • Use Ids for crossing aggregates.

NamingStrategy

There is a PR for @Column and @Table annotations

Events

@Bean
ApplicationListener<BeforeDelete> softDeleteListener() {

  return event -> {

    DummyEntity entity = (DummyEntity) event.getOptionalEntity()
        .orElseThrow(AssertionFailedError::new);

    entity.deleted = true;
    List<DbAction> actions = event.getChange().getActions();
    actions.clear();
    actions.add(DbAction.update(entity, null, null));
  };
}

Sorry no pagination yet

MyBatis integration

Inofficial Boot Starter

Default Answer

  • No that feature doesn’t exist yet.

  • We accept pull requests.

Google Spanner

Cloud Spanner is the only enterprise-grade, globally-distributed, and strongly consistent database service built for the cloud specifically to combine the benefits of relational database structure with non-relational horizontal scale.

TOQAEFT

The One Question Asked Every Freaking Time

Is there reactive support for JPA/JDBC?

TL;DR: No.

Long Version

JPA is unfit for a reactive API.

Won’t happen.

JDBC

JDBC is also blocking and will stay this way.

Oracle Works on an Async SQL-API

Not Flow/Reactive Stream based

Does that sound familiar?

2004

EJBs

Anybody remembers the time?

R2DBC

Reactive Relational Database Connectivity

There is a project exploring possibilities: https://github.com/nebhale/r2dbc

Questions?

I’ll be here.

Find me and ask away.

Everybody else: Have a nice day and thanks for the fish.

Jens Schauder

Dad, Board&Roleplaying Gamer, Runner, Freeletics Masochist

+

JUG Organizer