我正在寻找Spring Data JPA。考虑下面的例子,我将得到所有的crud和查找器功能默认工作,如果我想自定义一个查找器,那么也可以在界面本身轻松完成。
@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {
@Query("<JPQ statement here>")
List<Account> findByCustomer(Customer customer);
}
我想知道如何添加一个完整的自定义方法及其实现以上AccountRepository?因为它是一个接口,我不能在那里实现方法。
公认的答案是可行的,但有三个问题:
在将自定义实现命名为AccountRepositoryImpl时,它使用了一个未记录的Spring Data特性。文档明确指出它必须被称为AccountRepositoryCustomImpl,即自定义接口名加上Impl
不能使用构造函数注入,只能使用@Autowired,这被认为是不好的做法
在自定义实现中有一个循环依赖(这就是为什么不能使用构造函数注入)。
我找到了一个让它变得完美的方法,尽管不是没有使用另一个未记录的Spring Data特性:
public interface AccountRepository extends AccountRepositoryBasic,
AccountRepositoryCustom
{
}
public interface AccountRepositoryBasic extends JpaRepository<Account, Long>
{
// standard Spring Data methods, like findByLogin
}
public interface AccountRepositoryCustom
{
public void customMethod();
}
public class AccountRepositoryCustomImpl implements AccountRepositoryCustom
{
private final AccountRepositoryBasic accountRepositoryBasic;
// constructor-based injection
public AccountRepositoryCustomImpl(
AccountRepositoryBasic accountRepositoryBasic)
{
this.accountRepositoryBasic = accountRepositoryBasic;
}
public void customMethod()
{
// we can call all basic Spring Data methods using
// accountRepositoryBasic
}
}
我用mongo和spring来解决这个问题。因此,让我们假设我们使用MongoRepository来提供基本的crud操作,并假设我们需要使用mongoTemplate实现一些自定义条件查询操作。为了实现为crud和custom注入存储库的一个接口,我们需要指定:
自定义接口:
public interface UserCustomRepository {
List<User> findAllUsersBySomeCriteria(UserCriteriaRequest criteriaRequest);
}
UserRepository接口“必须”首先扩展UserCustomRepository,然后扩展MongoRepository
@Repository
public interface UserRepository extends UserCustomRepository, MongoRepository<User, ObjectId> {
}
UserRepositoryImpl必须与带有*Impl后缀的crud接口同名。
@Component
@NoArgsConstructor
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class UserRepositoryImpl implements UserCustomRepository {
private MongoTemplate mongoTemplate;
@Override
public List<User> findAllUsersBySomeCriteria(UserCriteriaRequest criteriaRequest){
//some impl
}
}
让我们来实现一些服务——这里我们只注入UserRepository接口,并使用来自crud存储库和自定义类impl的方法。
@Service
@NoArgsConstructor
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class UserService {
private UserRepository userReposityry;
public List<User> getUserByCriteria(UserCriteriaRequest request) {
userRepository.findById(request.getUserId); // Crud repository method
userRepository.findAllUsersBySomeCriteria(request); // custom method.
}
}
这里还有一个问题需要考虑。有些人希望将自定义方法添加到存储库中将自动将其作为'/search'链接下的REST服务公开。不幸的是,事实并非如此。Spring目前不支持这一点。
这是“设计”特性,spring data rest显式检查方法是否为自定义方法,并且不会将其作为rest搜索链接公开:
private boolean isQueryMethodCandidate(Method method) {
return isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method);
}
这是Oliver Gierke的一段话:
这是有意为之。自定义存储库方法不像查询方法那样
它们可以有效地实现任何行为。因此,它目前是
我们不可能决定HTTP方法来公开方法
下。POST是最安全的选择但这与
泛型查询方法(接收GET)。
欲了解更多详细信息,请参阅此问题:https://jira.spring.io/browse/DATAREST-206
公认的答案是可行的,但有三个问题:
在将自定义实现命名为AccountRepositoryImpl时,它使用了一个未记录的Spring Data特性。文档明确指出它必须被称为AccountRepositoryCustomImpl,即自定义接口名加上Impl
不能使用构造函数注入,只能使用@Autowired,这被认为是不好的做法
在自定义实现中有一个循环依赖(这就是为什么不能使用构造函数注入)。
我找到了一个让它变得完美的方法,尽管不是没有使用另一个未记录的Spring Data特性:
public interface AccountRepository extends AccountRepositoryBasic,
AccountRepositoryCustom
{
}
public interface AccountRepositoryBasic extends JpaRepository<Account, Long>
{
// standard Spring Data methods, like findByLogin
}
public interface AccountRepositoryCustom
{
public void customMethod();
}
public class AccountRepositoryCustomImpl implements AccountRepositoryCustom
{
private final AccountRepositoryBasic accountRepositoryBasic;
// constructor-based injection
public AccountRepositoryCustomImpl(
AccountRepositoryBasic accountRepositoryBasic)
{
this.accountRepositoryBasic = accountRepositoryBasic;
}
public void customMethod()
{
// we can call all basic Spring Data methods using
// accountRepositoryBasic
}
}