Mixing in Spring Data Annotations

Viewed 215

As I am gradually trying to remove Dependencies on Spring in the domain part of my library without minimal extra effort, I now turn to Spring Data and the Repositories

Originally we annotated our domain entities to look like this:

@Document
public void MyEntity {
    @Id
    @Getter private final EntityIdentifier identifier;

    @PersistenceConstructor
    public MyEntity( ... ) {}
    ...
}

and so on. where @Document, @PersistenceConstructor and @Id originate from the Spring Project and some are for a specific database backend (MongoDB).

I would like to cut this dependency and use my own annotations, that make sense in my domain - @Document is definitly nothing my domain experts would understand when appearing on e.g an clas Chair or a Desk.

For de/serialization with Jackson, I can create mixins to add specific annotations to classes without modifying them in their origin.
Maybe there is a similar technique for Spring or some other way to achive this that is more elegant than creating a wrapping class?


Apparently I need some clarification:

Lets suppose we try to write a clean architecture application which consists out of the following modules: domain, adapters, application. In the domain module, I have my domain logic and domain entities and everything domainy. I do not have anything springy - no dependency on spring whatsoever, not even by having a dependency that somehow depends on spring.
In the adapters and application module, I do have dependencies on spring. I might use spring-data to implement the Repository-Adapters. I will use Spring to configure and glue together the application.

Now, in my domain module I have the following classes:

@AllArgsConstructor
@HashAndEquals(of="identifier")
@DomainEntity  // <-- This is an Annotation that has no dependency on Spring!
public class DomainEntity {
    @DomainId // <-- This is an Annotation that has no dependency on Spring!
    @Getter private final DomainEntityIdentifier identifier;

    @Getter @Setter private String someValue;
    ...
}

@HashAndEquals
@AllArgsConstructor
public class DomainEntityIdentifiers {
    @Getter private final String name;
} 

public void interface DomainEntityRepository {
     DomainEntity findById(DomainEntityIdentifier identifier);
     void save(DomainEntity domainEntity)
     void deleteById(DomainEntityIdentifier identifier);
}

Now the task is, to provide the implementation of that interface in the adapters module, using Spring Data - e.g. spring-data-mongo and inject this adapter to the domain in the application module.

Now, surly I can create an class, lets say DomainEntityMongo which is basically the same as the DomainEntity just with the spring-data-mongo-annotations, then a public interface MyEntityRepository extends CrudRepository<EntityIdentifier, MyEntityMongo> and implement the interface DomainRepository by using MyEntityRepository and converting there and back again between DomainEntityMongo <=> DomainEntity.

What I am looking for is a more magical/generical solution. E.g.

  • Having jackson-style mixin-classes, which provide Spring with the necessary/missing meta-data to do the work
  • Configuring Spring to use non-spring-annotations to do the work (just as it is possible with the ComponentScan for non-component-inheriting Annotations)
  • Or - if the data guys have crafted another innovative solution - this innovative solution.
1 Answers

you can use @JsonDeserialize(using = yourCustomizedDeserializer.class) have a look here https://www.baeldung.com/jackson-deserialization

you can customize your persistence strategy with @Persister. You may, for example, specify your own subclass of org.hibernate.persister.EntityPersister or you might even provide a completely new implementation of the interface org.hibernate.persister.ClassPersister that implements persistence via, for example, stored procedure calls, serialization to flat files or LDAP.

is that what you are looking for?

Related