Spring Boot扩展CrudRepository

17

我在一个Spring Boot应用程序中使用Hibernate。我正在为我的所有模型对象创建一个新的CrudRepository,以执行基本的CRUD任务。它们看起来像这样:

@Repository
public interface FoobarCrudRepo extends CrudRepository<Foobar, Long> {
}

但是我总是需要做一些额外的事情,比如使用不等式进行自定义搜索查询等。我会按照以下模式进行操作:

@Repository
public class FoobarDao {

    @PersistenceContext
    EntityManager em;

    public List<Foobar> findFoobarsByDate(Date date) {
        String sql = "select fb from Foobar fb where createdDate > :date";
        ...
        return query.getResultList();
    }
}

我的问题是,我能把这两个概念合并到一个类中吗?我尝试将它变成一个抽象类,就像这样:

我的问题是,是否可以将这两个概念合并为一个类?我尝试将其制作为抽象类,如下所示:

@Repository
public abstract class FoobarCrudRepo extends CrudRepository<Foobar, Long> {

    @PersistenceContext
    EntityManager em;

    public List<Foobar> findFoobarsByDate(Date date) {
        String sql = "select fb from Foobar fb where createdDate > :date";
        ...
        return query.getResultList();
    }

}

然而,Spring没有为它创建一个bean。

我该如何实现这个呢?

谢谢!


2
如果你正在使用spring-boot,那么你一定应该使用spring-boot jpa。我认为这是最好的选择。你甚至不需要编写DAO类。 - pmverma
5个回答

26

你可以有很多方法来达成这个目标。如果你真的需要绝对的控制,请尝试以下方法。

interface FoobarRepositoryCustom{
    List<Foobar> findFoobarsByDate(Date date);
}

interface FoobarRepository extends CrudRepository<Foobar, Long>, FoobarRepositoryCustom

public class FoobarRespoitoryImpl implements FoobarRepositoryCustom{
    @PersistenceContext private EntityManager em;


    public List<Foobar> findFoobarsByDate(Date date) {
    String sql = "select fb from Foobar fb where createdDate > :date";
    ...
    return query.getResultList();
    }
}

你还有另一种更简单的选择,就是根据方法名称自动生成查询语句。在你的例子中,你可以把这个代码添加到FoobarCrudRepo,Spring 会为你完成其余操作,假设Foobar有名为CreatedDate的属性。

List<Foobar> findByCreatedDateGreaterThan(Date date);

关于Spring如何基于方法名生成查询,请参考此链接


2
你的链接带我到了http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query,我认为这是一个更好的方法,因为它更易于阅读和更明确。非常好的答案! - James Watkins
我尝试了绝对控制的方法来覆盖存储库的deleteById方法。这迫使我显式地转换我的repo,如((FoobarRespoitoryImpl) repo).findFoobarsByDate(date);。有没有办法避免这种情况? - SchreiberLex
1
您可以通过扩展CrudRepository来创建自定义基础存储库。您需要使用@NoRepositoryBean进行注释,以便它不会被识别为存储库。 - revau.lt

1

完全不了解Spring Data,但经过一番搜索,我的印象是您无需离开接口即可创建自定义逻辑 - 您可以创建一个带注释的接口方法、遵循特殊命名方案的接口方法或带有自定义逻辑的默认接口方法:

enter image description here Baeldung:Spring入门中的屏幕截图。

这里是文档链接。请注意 "表格4.支持方法名称内关键字",可以用于创建接口方法,其名称向代码生成器传达关于要创建哪个查询的信息(参见下面的部分表格)。

enter image description here


0

这里的问题出在 abstract 关键字上。

@Repository
public abstract class FoobarCrudRepo extends CrudRepository<Foobar, Long>

Spring不会为一个非具体类创建bean,这就是你得到它的bean的原因。


2
在接口上使用@Repository是有效的。因此,它不是具体类与此无关。显然,它“不是接口”在这里起了作用,但为什么? - James Watkins

0

我们可以使用JPA EntityManager 进行直接的SQL操作:

public interface VerificationsRepository extends
    CrudRepository<Verification, Integer>,
    DAOAccess
{ }

interface DAOAccess {
   List findByEmail(String email);

}

class DAOAccessImpl implements DAOAccess {
   @PersistenceContext private EntityManager em;

    public List findByEmail(String email) {
        String sql =
            "select * from verifications where email = ?";
        Query query = em.createNativeQuery(sql, Verification.class)
            .setParameter(1, email);
        return query.getResultList();
    }
}

0

这是对我有效的方法...

@SpringBootApplication(scanBasePackages = { "com.myproject" })
@EnableJpaRepositories(basePackages="com.myproject.sprinbootapp.repository")
    @EntityScan("com.myproject.sprinbootapp.model")
    public class SpringbootAppWithDatabaseApplication {

        public static void main(String[] args) {
            SpringApplication.run(SpringbootAppWithDatabaseApplication.class, args);
        }
    }

@Service
public class TopicService {

    @Autowired
    private TopicRepository topicRepository;

    private List<Topics> topics = new ArrayList<Topics>();

    public List<Topics> getAllTopics(){
        List<Topics> listOfTopics = new ArrayList<Topics>();
        topicRepository.findAll().forEach(listOfTopics::add);;
        return listOfTopics;
    }

}

@Entity
public class Topics {

    @Id
    private String id;

    private String name;

    public Topics(){

    }
 getters and setters...
}

public interface TopicRepository extends CrudRepository<Topics, String> {

}

1
为什么要遍历列表,findAll 已经给你一个列表了呢? - boutta

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