书接上文
自从上一篇 Blog 发出以后,有佬友提出了这样一种观点:「我管你这那的,数据库我只用增删改查,连分页都不用一样能写程序」。
这篇文章不讨论这种做法的对错,只介绍 JOOQ 针对这种使用方式的解决方案。
Simple CRUD
上述的使用方式在数据库操作中有个专业名词,叫做 Simple CRUD。这不是什么神奇的功能,大多数数据操作库都会提供这个功能的解决方案。当然,原始的 Mybatis 没有这个功能——所以我们常说:Mybatis 是一个上古时代的框架。
言归正传,对于这样一个 SQL 来说,Mybatis Plus 和 JOOQ 中的 Simple CRUD 分别如下所示:
SELECT * FROM user WHERE username = 'John';
Mybatis Plus
public interface UserMapper extends BaseMapper<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", "John");
List<User> userList = userMapper.selectList(queryWrapper);
JOOQ
@Autowired private DSLContext dsl;
List<User> users = dsl.selectFrom(USER).where(USER.USERNAME.eq("John")).fetchInto(User.class);
DSLContext 是什么
JOOQ 不需要什么额外的样板代码,DSLContext 就是 JOOQ 和数据库交互的核心 API——当和 SpringBoot 进行集成时,通过 @Autowired private DSLContext dsl
便可在任意地方注入进行使用,就算你在 Controller 里面用也可以。
Q:有好事者问了,那我不用 SpringBoot,使用 JOOQ 还像这样方便吗?
A:是的,那更方便了。
DSL.selectFrom(USER).fetch()
查询数据
上面我们已经介绍过了,除此之外还能使用 fetchOne
等其他变体。
User user = dsl.selectFrom(USER).fetchOne();
插入数据
通过 newRecord
创建的对象叫做 UpdatableRecords
,这是一个隐含了数据库链接的对象,store
就是插入数据的方法。
UserRecord userRecord = dsl.newRecord(USER);
userRecord.setUsername("[email protected]");
userRecord.setPassword("falr2b9nCVY5hS1o");
userRecord.store();
更新数据
store
是一个 upsert
操作,它不仅能够插入数据,还能够更新数据。这是全自动的,当对象在数据库里已经存在时,再调用 store
就是更新操作。
// 插入新数据
UserRecord userRecord = dsl.newRecord(USER);
userRecord.setUsername("[email protected]");
userRecord.setPassword("falr2b9nCVY5hS1o");
userRecord.store();
// userRecord 插入完毕后再次调用 store 则自动更新
userRecord.setPassword("JHMDoQPKuEcgILE6");
userRecord.store();
删除数据
UserRecord userRecord = dsl.fetchOne(USER, USER.USERNAME.eq("testUserA"));
userRecord.delete();
刷新数据
一个被查询出的UpdatableRecords
代表的数据库状态可能不是最新的,因为别的线程可能在你之后改变了数据库状态。调用 refresh
可以刷新对象的属性为数据库的最新状态。
// 线程A
UserRecord fetchedOne = dsl.fetchOne(USER, USER.USERNAME.eq("[email protected]"));
assertThat(fetchedOne.getPassword()).isEqualTo("falr2b9nCVY5hS1o");
// 线程B
userRecord.setPassword("JHMDoQPKuEcgILE6");
userRecord.store();
// 线程A
fetchedOne.refresh();
assertThat(fetchedOne.getPassword()).isEqualTo("JHMDoQPKuEcgILE6");
致其他语言的开发者
虽然 JOOQ 不是一个 ORM(Mybatis 当然更不是),但是对于使用 C# 和 PHP 及 Ruby 的开发者来说,当你在项目中不得不使用 Java 时,JOOQ 会不会稍微让你对这个领域的 CRUD 生态提起一点点信心?
写在最后
我是 Chuck1sn,一个长期致力于现代 Jvm 生态推广的开发者。您的回帖、点赞、收藏、就是我持续更新的动力;举手之劳的一键三连对我来说是莫大的支持,非常感谢!还可关注我的账号,第一时间收到文章推送。