spring-data-jdbc的基础使用(一)

前言#

很多人知道Mybatis,知道Jpa,但是对spring-data-jdbc可能了解的少之又少。注意我们这里说的是data-jdbc,而不是普通的jdbc。它拥有了类似jpa的一些特性,比如能够根据方法名推导出sql,基本的CRUD等,也拥有了写原生sql的能力。最为关键的是,它非常的清爽,不需要依赖hibernte或者jpa。

一、使用https://start.spring.io/ ,建立一个demo#

file

二、使用 Java 配置的 Spring Data JDBC#

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
// @EnableJdbcRepositories 为接口Repository 创建实现 //AbstractJdbcConfiguration 提供 Spring Data JDBC 所需的各种默认 bean @Configuration @EnableJdbcRepositories(basePackages = "com.example.springdatajdbctest") public class ApplicationConfiguration extends AbstractJdbcConfiguration { /** * 创建DataSource,使用springboot的默认的连接池,当然你也可以使用druid * ConfigurationProperties注解,去配置项中找spring.datasource开头的配置项,来创建DataSource */ @Bean @ConfigurationProperties(prefix="spring.datasource" ) public DataSource dataSource() { return DataSourceBuilder.create().build(); } /** * 官方使用内置的数据库类型 @Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder.setType(EmbeddedDatabaseType.H2).build(); } */ /** * NamedParameterJdbcOperations是Spring Data JDBC 用来访问数据库的 * @param dataSource * @return */ @Bean NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) { return new NamedParameterJdbcTemplate(dataSource); } /** * 提供的事务管理 * @param dataSource * @return */ @Bean TransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }

对应的application.properties内容如下:

Copy Line-numbers highlighter-prismjs language-xml prismjs-lines-highlighted code-theme-dark
spring.datasource.jdbc-url = jdbc:mysql://127.0.0.1/sss?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useAffectedRows=true spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.datasource.username = root spring.datasource.password = ****

三、数据库建表、建实体类#

Copy Line-numbers highlighter-prismjs language-sql prismjs-lines-highlighted code-theme-dark
create table user_info ( id int auto_increment primary key, name varchar(32) not null, age int not null, sex tinyint default 1 not null, create_time datetime not null, update_time datetime not null ) comment '用户表';
Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Data public class UserInfo extends BaseEntity{ /** * ID注解需要加上,标记为主键,否则无法识别主键 * 其他字段不需要加对应的列明,表名也可以不加注解,前提是类名、字段名符合标准的驼峰命名规范,否则无法对应上 */ @Id private Integer id ; private String name; private Integer age; private Integer sex; } @Data public class BaseEntity { private LocalDateTime createTime; private LocalDateTime updateTime; }

四、建立仓储接口UserInfoRepository#

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
/** * 这里CrudRepository接口已经提供了常见的一些接口,因此这里继承CrudRepository */ public interface UserInfoRepository extends CrudRepository<UserInfo, Integer> { }
Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
/** * 也可以继承PagingAndSortingRepository,它继承了CrudRepository,多了排序和分页默认方法 */ public interface UserInfoRepository extends PagingAndSortingRepository<UserInfo, Integer> { }

五、运行一下:#

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@SpringBootTest @RunWith(SpringRunner.class) class SpringDataJdbcTestApplicationTests { @Autowired private UserInfoRepository userInfoRepository; @Test public void testGet() { Optional<UserInfo> userInfo = userInfoRepository.findById(1); System.out.println(userInfo.get()); } @Test public void testCount() { long count = userInfoRepository.count(); System.out.println(count); }

}

file

六、关键字查询方法#

如果默认方法中没有我们需要的方法,我们还可以按规则来编写关键字查询方法。可以通过带有关键字的方法名来解析出SQL,比如

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
public interface UserInfoRepository extends PagingAndSortingRepository<UserInfo, Integer> { List<UserInfo> findByName(String ame); }

这样无需写SQL语句,就能查询出我们想要的结果。这里使用的是关键字findBy后面的既是需要的查询条件,当然还支持复合查询。比如

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
List<UserInfo> findByNameAndAge(String name,Integer age);

当然还支持其他的关键字查询。见下表
file
关键字方式,仅限于可以在WHERE不使用连接的情况下在子句中使用的属性

再如果你不喜欢这种关键字方式,可以自定义方法名字,你还可以使用@Query方式进行定义查询方法

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Query("select name, age from user_info u where u.name = :name") List<UserInfo> getUserInfoByName(String name);

如果你要修改或者删除,只需要增加注解@Modifying,语句如下:

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Modifying @Query("update user_info set age=:age where name = :name") Boolean updateAgeById(String name,Integer age); @Modifying @Query("delete from user_info where id = :id") Boolean deleteRecord(Integer id);

是不是感觉很方便,不再用去写SQL了

七、生命周期的事件机制#

Spring Data JDBC 的操作可以作为事件和ApplicationListener的事件相结合
比如,监听所有插入前的操作,这里我们只演示打印日志:

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Configuration @Slf4j public class CommonEventConfiguration { @Bean public ApplicationListener<BeforeSaveEvent<Object>> loggingSaves() { return event -> { Object entity = event.getEntity(); log.info("{} is getting saved.", entity); }; } }

当然你不想对所有的操作都监听处理,你可以指定具体某一个表的操作,如下:

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Slf4j @Repository public class UserSavedListener extends AbstractRelationalEventListener<UserInfo> { @Override protected void onAfterSave(AfterSaveEvent<UserInfo> userInfoAfterSaveEvent) { log.info("用户:{},保存成功",userInfoAfterSaveEvent.getEntity()); } }

执行测试代码:

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Test public void testInsert() { UserInfo userInfo =new UserInfo(); userInfo.setName("王五"); userInfo.setAge(20); userInfo.setSex(1); UserInfo result = userInfoRepository.save(userInfo); System.out.println(result); }

执行结果:
file

可用事件有:
file

八、实体回调#

Spring Data 基础设施提供了在调用某些方法之前和之后修改实体的钩子。也许你已经注意到了,user_info表的创建时间和更新时间我们没有赋值,数据库里的两个时间都是有值的,这就是用实体回调来实现的。

建立一个实体回调类

Copy Line-numbers highlighter-prismjs language-java prismjs-lines-highlighted code-theme-dark
@Component public class DefaultingEntityCallback implements BeforeSaveCallback<BaseEntity> { @Override public BaseEntity onBeforeSave(BaseEntity baseEntity, MutableAggregateChange<BaseEntity> mutableAggregateChange) { baseEntity.setCreateTime(LocalDateTime.now()); baseEntity.setUpdateTime(LocalDateTime.now()); return baseEntity; } }

另外一种场景,在查询结果出来后需要将用户的敏感信息脱敏,则可以使用AfterLoadCallback实体回调

完结

posted @   程序员阿牛  阅读(2058)  评论(0编辑  收藏  举报
编辑推荐:
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
阅读排行:
· 20250116 支付宝出现重大事故 有感
· 一个基于 Roslyn 和 AvalonEdit 的跨平台 C# 编辑器
· 推荐一款非常好用的在线 SSH 管理工具
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· .NET周刊【1月第1期 2025-01-05】
点击右上角即可分享
微信分享提示
CONTENTS