在前几节中,我们了解了ORM(对象关系映射)的基本概念,它通过ResultSet到JavaBean的映射,简化了数据库操作。ORM框架通过不同的实现方式提供了灵活性,有的像Hibernate和JPA,通过全自动化的机制进行对象映射和查询,而MyBatis则提供了更大的控制权,要求手动编写SQL语句。今天,我们将通过Spring框架实现一个简单高效的ORM。
1. ORM的基础
ORM(Object-Relational Mapping)本质上是将数据库中的表结构与Java类进行映射,从而简化了数据存取操作。常见的ORM框架有:
-
Hibernate/JPA:全自动化的ORM框架,支持透明的代理对象和自动跟踪Entity修改。
-
MyBatis:需要手动编写SQL,不包含透明的代理和自动映射的功能。
虽然Hibernate和JPA自带了HQL和JPQL查询语法,MyBatis则完全手动编写SQL,增加查询时,需要先编写SQL并创建接口方法。
示例:Hibernate和JPA的Criteria查询
Hibernate的Criteria查询:
javaDetachedCriteria criteria = DetachedCriteria.forClass(User.class);criteria.add(Restrictions.eq("email", email)).add(Restrictions.eq("password", password));List<User> list = (List<User>) hibernateTemplate.findByCriteria(criteria);
JPA的Criteria查询:
javavar cb = em.getCriteriaBuilder();CriteriaQuery<User> q = cb.createQuery(User.class);Root<User> r = q.from(User.class);q.where(cb.equal(r.get("email"), cb.parameter(String.class, "e")));TypedQuery<User> query = em.createQuery(q);query.setParameter("e", email);List<User> list = query.getResultList();
虽然JPA的查询写法较为复杂,但它提供了强大的查询功能,特别适合需要动态查询的场景。
2. 设计一个简单的ORM框架
本节我们将通过Spring框架来设计一个简单的ORM。我们不需要实现完整的自动化映射(如Hibernate那样的复杂关系管理),而是以简洁、易用为目标,兼顾灵活性和可扩展性。
设计目标
-
简洁易用:覆盖95%的应用场景,简单的SQL可以通过流式API快速生成。
-
灵活性:对于复杂的SQL需求,提供原生JDBC接口支持。
-
透明性:不需要为每个Entity创建代理,避免复杂的状态管理。
ORM接口设计
我们希望设计一个简单且清晰的接口,使用流式API构建查询条件。以下是以User类为例的查询接口设计:
java// 按主键查询User u = db.get(User.class, 123);// 条件查询唯一记录User u = db.from(User.class).where("email=? AND password=?", "bob@example.com", "bob123").unique();// 条件查询多条记录List<User> us = db.from(User.class).where("id < ?", 1000).orderBy("email").limit(0, 10).list();// 查询特定列User u = db.select("id", "name").from(User.class).where("email = ?", "bob@example.com").unique();
对于插入、更新和删除操作:
java// 插入Userdb.insert(user);// 更新Userdb.update(user);// 删除Userdb.delete(User.class, 123);
设计数据库操作接口
为了使ORM更加简洁易用,我们使用流式API来支持查询、插入、更新和删除操作。接下来我们定义一个DbTemplate类,它封装了Spring的JdbcTemplate,并通过流式API提供简洁的接口。
3. 实现ORM框架
3.1 配置Spring环境
在AppConfig中,我们初始化所有Bean,包括数据源、JdbcTemplate和DbTemplate等:
java@Configuration@ComponentScan@EnableTransactionManagement@PropertySource("jdbc.properties")public class AppConfig {@BeanDataSource createDataSource() { ... }@BeanJdbcTemplate createJdbcTemplate(@Autowired DataSource dataSource) {return new JdbcTemplate(dataSource);}@BeanDbTemplate createDbTemplate(@Autowired JdbcTemplate jdbcTemplate) {return new DbTemplate(jdbcTemplate, "com.itranswarp.learnjava.entity");}@BeanPlatformTransactionManager createTxManager(@Autowired DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}}
3.2 编写业务逻辑
在业务逻辑层,我们可以通过DbTemplate执行数据库操作。例如,我们在UserService中使用ORM接口进行数据查询和操作:
java@Component@Transactionalpublic class UserService {@AutowiredDbTemplate db;public User getUserById(long id) {return db.get(User.class, id);}public User getUserByEmail(String email) {return db.from(User.class).where("email = ?", email).unique();}public List<User> getUsers(int pageIndex) {int pageSize = 100;return db.from(User.class).orderBy("id").limit((pageIndex - 1) * pageSize, pageSize).list();}public User register(String email, String password, String name) {User user = new User();user.setEmail(email);user.setPassword(password);user.setName(name);user.setCreatedAt(System.currentTimeMillis());db.insert(user);return user;}}
3.3 实现DbTemplate
DbTemplate类封装了JdbcTemplate,提供查询、插入、更新、删除等操作:
javapublic class DbTemplate {private JdbcTemplate jdbcTemplate;private Map<Class<?>, Mapper<?>> classMapping;public <T> T fetch(Class<T> clazz, Object id) {Mapper<T> mapper = getMapper(clazz);List<T> list = (List<T>) jdbcTemplate.query(mapper.selectSQL, new Object[] { id }, mapper.rowMapper);if (list.isEmpty()) {return null;}return list.get(0);}public <T> T get(Class<T> clazz, Object id) {...}public <T> void insert(T bean) {...}public <T> void update(T bean) {...}public <T> void delete(Class<T> clazz, Object id) {...}}
3.4 实现链式查询
通过select()或from()方法,DbTemplate会实例化一个CriteriaQuery对象,在后续的链式调用中,我们可以逐步设置查询条件、排序、限制等:
javapublic class DbTemplate {public Select select(String... selectFields) {return new Select(new Criteria(this), selectFields);}public <T> From<T> from(Class<T> entityClass) {Mapper<T> mapper = getMapper(entityClass);return new From<>(new Criteria<>(this), mapper);}}
在From中,可以设置表名和实体类类型,而Where方法则允许设置查询条件:
javapublic final class From<T> extends CriteriaQuery<T> {public Where<T> where(String clause, Object... args) {return new Where<>(this.criteria, clause, args);}}
3.5 返回结果
链式调用的终点是调用list()获取多个结果,或者调用unique()获取唯一结果,或者调用first()获取第一个结果。
4. 小结
通过这节的学习,我们设计并实现了一个简单高效的ORM框架,利用Spring的JdbcTemplate进行底层数据库操作,并提供流式API使得数据库操作更加简洁和易用。这个框架能覆盖大部分常见的查询需求,且对于复杂SQL场景,也提供了直接使用JDBC的方式来处理。
如果你有兴趣深入实现完整的ORM框架,可以根据本节提供的思路和代码,逐步完善各个功能模块。
练习
设计并实现一个微型ORM,结合本节的内容,扩展ORM框架的功能,例如支持事务管理、连接池等。
748

被折叠的 条评论
为什么被折叠?



