/less-popular-spring

Less popular Spring tricks: no Hibernate, rest repo, projections

Primary LanguageJava

Less popular Spring tricks: no Hibernate, rest repo, projections

Typical Spring project

  • JPA (usually Hibernate ORM), @Entity classes here and there, Flyway for DB migrations
  • Spring Data - SQL for above classes; especially JpaRepository
  • Entity-DTO mapping, usually done by hand
  • @Controller or @RestController exposing DTOs

This project

  • Still with Flyway
  • Still with Spring Data
  • No JPA, no "manual" mappings, fancy REST (HATEOAS)

Example code

Perfect catalog-like CRUD application. The main (and only) entity is called Category and thanks to carwarninglights.net I made it displaying car segments.

From the first view it looks typical - there is a file-based H2 SQL database, it can be started easily and with src/main/resources/Less popular Spring tricks.postman_collection.json anyone can use Postman to check it in action.

However, code itself can be a little confusing. There is no JPA, no Spring Data JPA dependency, you cannot extend a typical JpaRepository. There are way more interfaces than classes and a familiarly looking TraditionalController doesn't seem to be used much. And git commits show it was built like that from the very beginning!

No Hibernate

⚠️ Disclaimer ⚠️

I got to know this Spring Data JDBC when I worked in the company which wasn't using Spring Framework at all. Seems it's a powerful tool, especially when combining with DDD approach, but I haven't seen this used on the production env.

Do you know we don't need Hibernate to use @Table annotation?

Spring Data JDBC comment

Spring Data JDBC

org.springframework.data.annotation and org.springframework.data.relational.core.mapping to the rescue!

Detailed documentation.

Rest Repo

⚠️ Disclaimer ⚠️

I'd personally use Rest Repositories just for read operations. Preferably built on top of the pure Repository interface. It can be a powerful thing for "query" part of the system, especially combined with projections. However, in practice it seems sooner or later you'd move towards a traditional approach which is more customizable than @RepositoryRestResource and @RestResource options, default interface methods and even RepositoryRestController.

Spring Data REST specifically. With its detailed documentation.

Projections

⚠️ Disclaimer ⚠️

I really like projections. In my eyes it's an easy opt-in solution which can be replaced with a hidden implementing class and ObjectMapper configs if needed.

Not only for above repositories, but also with a more "traditional" approach:

//                                                 👇
interface CategoryRepository extends Repository<Category, Long> {

    //        👇
    List<TextCategoryVM> findTextualCategoriesBy();
}

@Getter
@NoArgsConstructor(access = PROTECTED)
@Table("categories")
class Category {

    @Id
    private Long id;
    @NotBlank
    private String code;
    @NotBlank
    private String name;
    private String description;
    private String imageUrl;
    @Column("is_deprecated")
    private boolean deprecated;
}

// getters "compatible" with the Category class
interface TextCategoryVM {

    String getCode();

    String getName();

    String getDescription();
}

Further read: