Spring 引导扩展 CrudRepository

Spring Boot extending CrudRepository

我在 Spring 启动应用程序中使用 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();
    }
}

我的问题是,我可以将这两个概念合并为一个 class 吗?我试着把它变成一个抽象的 class,像这样:

@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。

我怎样才能做到这一点?

谢谢!

这里的问题是 abstract 关键字。

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

Spring 不会为 class 创建 bean,除非它是具体的 class。 这就是为什么你会得到一个豆子。

您可以通过多种方式完成此操作。如果你真的需要绝对控制,试试这个

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 如何根据方法名称生成查询的参考,请参阅此 http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation

完全是 Spring 数据的新手,但经过一些搜索,我的印象是您不必离开接口来创建自定义逻辑 - 而是您可以创建一个带注释的接口方法,一个接口遵循特殊命名方案或具有自定义逻辑的默认接口方法的方法:

来自 Baeldung: Introduction to Spring.

的屏幕截图

Here is a link to the documentation. Notice "table 4. Supported keywords inside method names”,可用于创建接口方法,其名称向代码生成器传达有关要创建哪个查询的信息(请参阅下面的 table 部分)。

这对我有用...

@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> {

}

我们可以使用 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();
    }
}