JPA和SQL在Spring Boot鱼和熊掌兼得 – Billy Korando

19-05-10 banq
         

JPA,Java Persistence API的设计目标是使Java开发人员更容易进行数据库交互。与Spring Data JPA等库一起使用时,只需几分钟即可完成基本的数据库通信设置。

Spring Data JPA在对一个或两个表执行相对简单的查询时效果很好,但是一旦开始超出这个基本复杂程度,就会变得难以处理。在实际应用程序中,一次查询三个,四个或更多表,以及在查询中执行其他复杂行为通常是必要的。不出所料,数据库围绕查询,过滤和解析大量数据进行了优化,更不用说数据库和应用程序之间的传输时间了。因此,即使复杂查询的逻辑可以通过JPA进行细分和实现,性能要求也可能需要将该行为保持为单个查询。

Spring Data JPA使处理大量平常的数据库活动变得更加容易,但是在更复杂的行为中遇到了一些痛苦。SQL可以处理非常复杂的行为,但需要编写大量的样板代码才能进行简单的选择和插入。当然必须有一种方法可以在一致的接口背后利用JPA和SQL的优势吗?

Spring Data JPA提供了创建自定义存储库接口和实现的能力,并将它们与Spring Data JPA提供的默认存储库接口相结合,创建了一个复合存储库。这允许应用程序通过单个一致的接口与数据库交互。让我们逐步创建自己的复合存储库,然后在我们的应用程序中引用它。

第一步自定义接口:

定义新的接口和方法签名。在这里,我正在创建'CustomBlogRepo'接口:

public interface CustomBlogRepo {
    Iterable findBlogsByContent(String content);
}

第二步实现接口:

接下来我们需要实现接口。在这个例子中,我使用JdbcTemplate来处理查询,但是在自定义存储库类中如何实现数据库行为没有任何限制。

public class CustomBlogRepoImpl implements CustomBlogRepo {
 
    private JdbcTemplate jdbcTemplate;
 
    protected CustomBlogRepoImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
 
    @Override
    public Iterable findBlogsByContent(String content) {
        return jdbcTemplate.query("SELECT * FROM Blogs WHERE body LIKE ?", new Object[] { "%" + content + "%" },
                new BlogRowMapper());
    }
 
    class BlogRowMapper implements RowMapper {
        @Override
        public Blog mapRow(ResultSet rs, int rowNum) throws SQLException {
            return new Blog(rs.getLong("id"), rs.getString("title"), rs.getString("body"));
        }
    }
}

其他几个要点,默认情况下,Spring Data JPA将扫描与自定义接口名称匹配的类CustomBlogRepo以及“Impl”的后缀名,这就是为什么这里实现名称一定要写成CustomBlogRepoImpl这个名字的原因。如果需要,可以自定义此行为。此外,实现类还必须位于Spring Data JPA扫描存储库的包中。这也是可配置的,如前面的链接所示。

最后,我们需要使用我们创建的定制接口扩展相应的Repository接口。这是一个示例:

public interface CustomBlogRepo extends CrudRepository, CustomBlogRepo {
 
}

 

         

1