当使用新的
Spring Data Evans发行版时,很高兴能够使用一些与
Java 8一起使用的一些好东西.其中一个是接口中的默认实现.下面的存储库使用QueryDSL来使查询类型安全.
我的问题是,在我写这篇文章之前,我使用了一个单独的UserRepositoryCustom接口的模式为findByLogin,然后另一个类UserRepositoryImpl,并在该类中,我将有@PersistenceContext获取当前的EntityManager.
当我没有课程时,如何获得EntityManager?甚至有可能吗
@Repository public interface UserRepository extends JpaRepository<User,UUID> { final QUser qUser = QUser.user; // How do I get the entityManager since this is a interface,i cannot have any variables? //@PersistenceContext //EntityManager entityManager; public default Optional<User> findByLogin(String login) { JPAQuery query = new JPAQuery(entityManager); User user = query .from(qUser) .where( qUser.deleter.isNull(),qUser.locked.isFalse(),qUser.login.equalsIgnoreCase(login) ) .singleResult(qUser); return Optional.ofNullable(user); } }
解决方法
只能使用默认方法来委派对其他存储库方法的调用.默认方法(按定义)不能访问实例的任何状态(因为接口没有).他们只能委托其他接口方法或调用其他类的静态方法.
实际上,使用reference documentation中描述的自定义实现是正确的方法.这是简短的版本供参考(以防其他人也想知道):
/** * Interface for methods you want to implement manually. */ interface UserRepositoryCustom { Optional<User> findByLogin(String login); } /** * Implementation of exactly these methods. */ class UserRepositoryImpl extends QueryDslRepositorySupport implements UserRepositoryCustom { private static final QUser USER = QUser.user; @Override public Optional<User> findByLogin(String login) { return Optional.ofNullable( from(USER). where( USER.deleter.isNull(),USER.locked.isFalse(),USER.login.equalsIgnoreCase(login)). singleResult(USER)); } } /** * The main repository interface extending the custom one so that the manually * implemented methods get "pulled" into the API. */ public interface UserRepository extends UserRepositoryCustom,CrudRepository<User,Long> { … }
请注意,命名约定在这里很重要(但是如果需要,可以进行自定义).通过扩展QueryDslRepositorySupport,您可以访问from(…)方法,以便您不必自己与EntityManager进行交互.
或者,您可以让UserRepository实现QueryDslPredicateExecutor并从存储库外部传递谓词,但是让您最终可以使用需要使用Querydsl(可能是不需要的)的客户端,另外您还没有获取可选的包装器类型OOTB.