When using the new Spring Data Evans release it\'s nice to be able to use some of the nice stuff that came with java 8. One of them is default implementations in interfaces. The
What i ended up doing is creating a repository base which has a getEntityManager()
But it isn't all straight forward to get the base class working with spring boot
// DomainRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;
import javax.persistence.EntityManager;
import java.io.Serializable;
@NoRepositoryBean
public interface DomainRepository extends JpaRepository {
EntityManager getEntityManager();
}
Then the implementation
// DomainRepositoryImpl.java
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import javax.persistence.EntityManager;
import java.io.Serializable;
public class DomainRepositoryImpl extends SimpleJpaRepository implements DomainRepository {
private EntityManager entityManager;
public DomainRepositoryImpl(Class domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.entityManager = entityManager;
}
public EntityManager getEntityManager() {
return entityManager;
}
}
But then spring needs to know how to create domain repositories so we need to create a factory.
// DomainRepositoryFactoryBean.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import javax.persistence.EntityManager;
import java.io.Serializable;
public class DomainRepositoryFactoryBean, T, I extends Serializable> extends JpaRepositoryFactoryBean {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new RepositoryBaseFactory(entityManager);
}
private static class RepositoryBaseFactory extends JpaRepositoryFactory {
private EntityManager entityManager;
public RepositoryBaseFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new DomainRepositoryImpl((Class) metadata.getDomainType(), entityManager);
}
protected Class> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
//to check for QueryDslJpaRepository's which is out of scope.
return DomainRepository.class;
}
}
}
And then to tell spring boot to use this factory when creating repositories
// DomainConfig.java
@Configuration
@EnableJpaRepositories(repositoryFactoryBeanClass = DomainRepositoryFactoryBean.class, basePackages = {"com.mysite.domain"})
@EnableTransactionManagement
public class DomainConfig {
}
and then change the UserRepository to use it instead.
@Repository
public interface UserRepository extends DomainRepository {
public default Optional findByLogin(String login) {
JPAQuery query = new JPAQuery(getEntityManager());
...
}
}