我正在寻找Spring Data JPA。考虑下面的例子,我将得到所有的crud和查找器功能默认工作,如果我想自定义一个查找器,那么也可以在界面本身轻松完成。

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

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

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


当前回答

这在使用上是有限的,但是对于简单的自定义方法,你可以使用默认的接口方法,比如:

import demo.database.Customer;
import org.springframework.data.repository.CrudRepository;

public interface CustomerService extends CrudRepository<Customer, Long> {


    default void addSomeCustomers() {
        Customer[] customers = {
            new Customer("Józef", "Nowak", "nowakJ@o2.pl", 679856885, "Rzeszów", "Podkarpackie", "35-061", "Zamknięta 12"),
            new Customer("Adrian", "Mularczyk", "adii333@wp.pl", 867569344, "Krosno", "Podkarpackie", "32-442", "Hynka 3/16"),
            new Customer("Kazimierz", "Dejna", "sobieski22@weebly.com", 996435876, "Jarosław", "Podkarpackie", "25-122", "Korotyńskiego 11"),
            new Customer("Celina", "Dykiel", "celina.dykiel39@yahoo.org", 947845734, "Żywiec", "Śląskie", "54-333", "Polna 29")
        };

        for (Customer customer : customers) {
            save(customer);
        }
    }
}

编辑:

在这个春季教程中,它是这样写的:

Spring Data JPA还允许您通过定义其他查询方法 简单地声明它们的方法签名。

因此,甚至可以像这样声明方法:

Customer findByHobby(Hobby personHobby);

如果对象Hobby是Customer的属性,那么Spring将自动为您定义方法。

其他回答

考虑到您的代码片段,请注意,您只能将本机对象传递给findBy###方法,假设您想要加载属于某些客户的帐户列表,一个解决方案是这样做,

@Query("Select a from Account a where a."#nameoffield"=?1")
List<Account> findByCustomer(String "#nameoffield");

确保要查询的表的名称与Entity类相同。 关于进一步的实现,请看看这个

这里还有一个问题需要考虑。有些人希望将自定义方法添加到存储库中将自动将其作为'/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

我喜欢Danila的解决方案,并开始使用它,但团队中的其他人都不喜欢为每个存储库创建4个类。Danila的解决方案是这里唯一一个让您在Impl类中使用Spring Data方法的解决方案。然而,我发现了一种只用一个类就能做到的方法:

public interface UserRepository extends MongoAccess, PagingAndSortingRepository<User> {

    List<User> getByUsername(String username);


    default List<User> getByUsernameCustom(String username) {
        // Can call Spring Data methods!
        findAll();

        // Can write your own!
        MongoOperations operations = getMongoOperations();
        return operations.find(new Query(Criteria.where("username").is(username)), User.class);
    }
}

您只需要某种方式来访问您的db bean(在本例中为MongoOperations)。MongoAccess通过直接检索bean提供了对所有存储库的访问:

public interface MongoAccess {
    default MongoOperations getMongoOperations() {
        return BeanAccessor.getSingleton(MongoOperations.class);
    }
}

其中BeanAccessor为:

@Component
public class BeanAccessor implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public static <T> T getSingleton(Class<T> clazz){
        return applicationContext.getBean(clazz);
    }

    public static <T> T getSingleton(String beanName, Class<T> clazz){
        return applicationContext.getBean(beanName, clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanAccessor.applicationContext = applicationContext;
    }

}

不幸的是,你不能在界面中@Autowire。您可以将bean自动装配到MongoAccessImpl中,并在接口中提供一个方法来访问它,但是Spring Data失败了。我不认为它期望看到Impl与PagingAndSortingRepository间接关联。

I扩展了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中。

我用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.
 }
}