Something I stumbled upon over my latest story that might be of use in the future.

When we have the perfect storm of entities inheriting with a discriminator column:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Entity
@Table(name = "T_TABLE")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(columnDefinition = "TYPE", name = "TYPE")
public class Parent{
/**snip**/
}

/**snip**/
@DiscriminatorValue(value = "TYPE1")
public class Type1Entity extends Parent {
/**snip**/
}


/**snip**/
@DiscriminatorValue(value = "TYPE2")
public class Type2Entity extends Parent {
/**snip**/
}

How do we create our Spring Data repos for these guys?

  1. Creating repository classes, managing things manually
  2. Extending Magic Repository interfaces.

Option 2 is actually possible to do with some intelligent typing on those interfaces. We need to create a few of them but in the end it allows us to use the Magic on these fellows as well:

First a read only base repository that contains our common queries:

1
2
3
4
5
6
@NoRepositoryBean //Read-Only
public interface BaseParentDAO<EntityType extends Parent> extends CrudRepository<EntityType, Long> {

    @Query("select e from #{#entityName} e") // #{#entityName} will be magically replaced by type arguments in children
    List<EntityType> findThemAll();
}

Then we can create one to query all items, both Type1Entity and Type2Entity:

1
2
3
public interface ParentDAO extends BaseParentDAO<Parent>, CrudRepository<Parent, Long> {
    // Everything from base inherited
}

And repos for our children as well:

1
2
3
4
5
6
7
public interface Type1EntityDAO extends BaseParentDAO<Type1Entity>, CrudRepository<Type1Entity, Long> {
    // Everything from base inherited
}

public interface Type2EntityDAO extends BaseParentDAO<Type2Entity>, CrudRepository<Type2Entity, Long> {
    // Everything from base inherited
}

And that is all we need.

This way you can use different daos based on what you want to query: all of them, all of type ones or all of type twos. With this approach you also gain type safety for saving/updating since you need to use the correct DAO to make it compile.