前言
作业的项目终于告一段落了暂时,这周继续进行日志系统的编写,只可惜这周开始练科三了,一开始是全天练车,导致每天写代码的时间减少了好多,后来时间进行了调整(早上四点半到七点半,晚上五点到七点多),也算有挺多的时间了。
(驾校不正规,练车两行泪)
需求
由于日志系统每天的数据量较大,随着时间的推移,有很多之前的数据可能就没用了,但是在数据表里放着就占资源,于是要删除三个月之前的数据,就需要自己写原生SQL语句了。
Jdbc
按照教程给的源码进行了功能的编写,由于没写单元测试,所以虽说功能实现了,但是还是有很大的缺陷的,后来问了一下潘老师,老师推荐使用的是JPA
@Override
public List getData() {
/\* 定义实现了RowCallbackHandler接口的对象\*/
RowCallbackHandler rowCallbackHandler \= new RowCallbackHandler() {
/\*\*
\* 该方法用于执行jdbcTemplate.query后的回调,每行数据回调1次。比如DayLog表中有两行数据,则回调此方法两次。
\* @param resultSet 查询结果,每次一行
\* @throws SQLException 查询出错时,将抛出此异常,暂时不处理。
\*/
@Override
public void processRow(ResultSet resultSet) throws SQLException {
DayLog dayLog \= new DayLog();
dayLog.setId(resultSet.getLong("id"));
dayLog.setDay(resultSet.getDate("day"));
dayLogs.add(dayLog);
logger.info(resultSet.toString());
}
};
String query \= "select \* from day\_log where \`day\` <= curdate() - interval 3 month";
jdbcTemplate.query(query,rowCallbackHandler);
return dayLogs;
}
@Override
public boolean delete()
{
String sql \= String.format("delete from day\_log where \`day\` <= curdate() - interval 3 month");
this.jdbcTemplate.update(sql);
return true;
}
}
JPA
后来找了好多博客,看了一下它的用法,发现还是挺好用的:
public interface LogRepository extends JpaRepository<Log , Long>, JpaSpecificationExecutor {
/**
* 根据月份查找所有记录
*
* @return
*/
@Query(value = "SELECT * FROM `log` where `timestamp` <= curdate() - interval 3 month",nativeQuery = true)
List<Log> getLogOfThreeMonth();
/**
* 根据月份删除所有记录
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query(value = "delete from log where `timestamp` <= curdate() - interval 3 month",nativeQuery = true)
void deleteLogOfThreeMonth();
}
@Query
JPA执行原生SQL语句,首先要让仓库继承 JpaRepository ,然后加@Query注解,value表示要执行的语句,对于nativeQuery = true ,有的博客是这样解释的:
有nativeQuery = true时,是可以执行原生sql语句,所谓原生sql,也就是说这段sql拷贝到数据库中,然后把参数值给一下就能运行了
没有nativeQuery = true时,就不是原生sql,而其中的select * from xxx中xxx也不是数据库对应的真正的表名,而是对应的实体名,并且sql中的字段名也不是数据库中真正的字段名,而是实体的字段名。
@Modifying
对于该注解的解释,官方给出的说明是这样的:
- As the queries themselves are tied to the Java method that executes them, you can actually bind them directly by using the Spring Data JPA @Query annotation
- rather than annotating them to the domain class.
You can modify queries that only need parameter binding by annotating the query method with @Modifying - The @Modifying annotation is only relevant in combination with the @Query annotation. Derived query methods or custom methods do not require this Annotation.
- Doing so triggers the query annotated to the method as an updating query instead of a selecting one.
- 由于查询本身绑定到执行它们的Java方法,实际上可以通过使用Spring Data JPA@Query注释直接绑定它们,而不是将它们注释到域类。
- 通过使用@Modifying注释查询方法,可以修改只需要参数绑定的查询
- @Modifying注释只与@Query注释结合使用。派生查询方法或自定义方法不需要此批注。
- 这样做将触发作为更新查询(更新、插入、删除)而不是选择查询注释到方法的查询。
也就是说,当我们要通过自已写的更新、插入、删除SQL语句来实现更新、插入、删除操作时,至少需要用两个步骤:
1.@Query来注入我们自定义的sql;
2.使用@Modifying来标注是一个更新类的自定义语句。
@Transactional
官方给出的说明是:.
By default, CRUD methods on repository instances are transactional. For read operations, the transaction configurationreadOnly
flag is set totrue
. All others are configured with a plain@Transactional
so that default transaction configuration applies. For details, see JavaDoc ofSimpleJpaRepository
. If you need to tweak transaction configuration for one of the methods declared in a repository, redeclare the method in your repository interface, as follows:_Example. Custom transaction configuration for CRUD_
默认情况下,存储库实例上的CRUD方法是事务性的。对于读取操作,事务配置readOnly标志设置为true。所有其他的都配置了一个普通的@Transactional,以便应用默认的事务配置。有关详细信息,请参见SimpleJpaRepository的JavaDoc。如果需要调整存储库中声明的方法之一的事务配置,请在存储库界面中重新声明该方法,如下所示:
例子。CRUD的自定义事务配置
对于更新查询(更新(UPDATE)、删除( DELETE))来说,都需要加@Transactional注解。
疑惑及解决
之前Repository类继承的都是CrudRepository
这个类,以实现save,delete等方法,但是为什么我继承JpaRepository
不影响save等操作呢,进入JpaRepository
这个类,然后发现它也是继承的其他的类:
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
他继承的这个类,继承的就是CrudRepository
:
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
这也解决了我另一个疑惑,为什么有的类继承的 PagingAndSortingRepository
对save等方法也没有影响,原来他也是继承的。
总结
有些东西看起来复杂,写起来还是挺顺手的,对于SQL这个东西,要了解的还是挺多的,毕竟现在用的语句还是查出来的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。