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'接口:
<b>public</b> <b>interface</b> CustomBlogRepo { Iterable findBlogsByContent(String content); }
第二步实现接口:
接下来我们需要实现接口。在这个例子中,我使用 JdbcTemplate 来处理查询,但是在自定义存储库类中如何实现数据库行为没有任何限制。
<b>public</b> <b>class</b> CustomBlogRepoImpl implements CustomBlogRepo { <b>private</b> JdbcTemplate jdbcTemplate; <b>protected</b> CustomBlogRepoImpl(JdbcTemplate jdbcTemplate) { <b>this</b>.jdbcTemplate = jdbcTemplate; } @Override <b>public</b> Iterable findBlogsByContent(String content) { <b>return</b> jdbcTemplate.query(<font>"SELECT * FROM Blogs WHERE body LIKE ?"</font><font>, <b>new</b> Object[] { </font><font>"%"</font><font> + content + </font><font>"%"</font><font> }, <b>new</b> BlogRowMapper()); } <b>class</b> BlogRowMapper implements RowMapper { @Override <b>public</b> Blog mapRow(ResultSet rs, <b>int</b> rowNum) throws SQLException { <b>return</b> <b>new</b> Blog(rs.getLong(</font><font>"id"</font><font>), rs.getString(</font><font>"title"</font><font>), rs.getString(</font><font>"body"</font><font>)); } } } </font>
其他几个要点,默认情况下,Spring Data JPA将扫描与自定义接口名称匹配的类CustomBlogRepo以及“Impl”的后缀名,这就是为什么这里实现名称一定要写成CustomBlogRepoImpl这个名字的原因。 如果需要,可以自定义此行为 。此外,实现类还必须位于Spring Data JPA扫描存储库的包中。这也是可配置的,如前面的链接所示。
最后,我们需要使用我们创建的定制接口扩展相应的Repository接口。这是一个示例:
<b>public</b> <b>interface</b> CustomBlogRepo <b>extends</b> CrudRepository, CustomBlogRepo { }