如何向Spring Data JPA添加自定义方法

220

我正在研究Spring Data JPA。考虑下面的示例,其中默认情况下将获得所有CRUD和查找器功能,如果我想自定义查找器,则可以在接口本身轻松完成。

@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {

  @Query("<JPQ statement here>")
  List<Account> findByCustomer(Customer customer);
}

我想知道如何为上述AccountRepository添加一个完整的自定义方法及其实现?由于它是一个接口,我不能在那里实现该方法。


接口自Java 8开始支持默认方法,不确定Spring Data是否支持此功能。 - Christoph Dahlen
13个回答

1

我在使用mongo和spring时遇到了这个问题。所以让我们假设我们使用MongoRepository来提供基本的crud操作,假设我们需要使用mongoTemplate实现一些自定义的条件查询操作。为了实现一个接口来注入用于crud和自定义的repository,我们需要指定:

自定义接口:

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存储库和自定义类实现的方法。

@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.
 }
}

哇;-) - 但这不是我们讨论的话题: 我从未见过@AllArgsConstructor(onConstructor = @__(@Autowired)),我该怎么想。很好还是最好按照标准方式实现,而不使用lombok。一个想法是它取决于你的同事(需要阅读代码的人)的设置。如果他们都熟悉它,那就没问题了。如果有人经常更改或不想熟悉lombok,可能会感到困惑。我可以猜测它看起来像一种将功能插入Java类/对象的新语法/方式。- 好吧,我刚刚查了一下:lombok称其为实验性的! - Dirk Schumacher
@RequiredArgsConstructor非常适用于设置构造函数注入 - 只需要将repo设置为private final,这样它就知道要放在构造函数中了。 - UpsideDownRide
@UpsideDownRide 你说得对,不需要添加参数:(onConstructor = @__(@Autowired)) - 它可以更简单:@AllArgsConstructor private final UserRepository userRepository; // 这里最重要的是 final 字段。 - mryba
@DirkSchumacher - 在我的观察中,Lombok在新项目中似乎非常受欢迎。它非常适合,不需要生成样板代码。但是团队仍然需要决定是否使用 :) - mryba

0

我继承了SimpleJpaRepository:

public class ExtendedRepositoryImpl<T extends EntityBean> extends SimpleJpaRepository<T, Long>
    implements ExtendedRepository<T> {

    private final JpaEntityInformation<T, ?> entityInformation;

    private final EntityManager em;

    public ExtendedRepositoryImpl(final JpaEntityInformation<T, ?> entityInformation,
                                                      final EntityManager entityManager) {
       super(entityInformation, entityManager);
       this.entityInformation = entityInformation;
       this.em = entityManager;
    }
}

并将此类添加到@EnableJpaRepositoryries repositoryBaseClass中。


0

我使用SimpleJpaRepository作为存储库实现的基类,并在接口中添加自定义方法,例如:

public interface UserRepository  {
    User FindOrInsert(int userId);
}

@Repository
public class UserRepositoryImpl extends SimpleJpaRepository implements UserRepository {

    private RedisClient redisClient;

    public UserRepositoryImpl(RedisClient redisClient, EntityManager em) {
        super(User.class, em);
        this.redisClient = redisClient;
    }


@Override
public User FindOrInsert(int userId) {

    User u = redisClient.getOrSet("test key.. User.class, () -> {
        Optional<User> ou = this.findById(Integer.valueOf(userId));
        return ou.get();
    });
    …………
    return u;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接