【Java教程】Day22-20 Spring框架:访问数据库—— ORM

在前几节中,我们了解了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 {    @Bean    DataSource createDataSource() { ... }    @Bean    JdbcTemplate createJdbcTemplate(@Autowired DataSource dataSource) {        return new JdbcTemplate(dataSource);    }    @Bean    DbTemplate createDbTemplate(@Autowired JdbcTemplate jdbcTemplate) {        return new DbTemplate(jdbcTemplate, "com.itranswarp.learnjava.entity");    }    @Bean    PlatformTransactionManager createTxManager(@Autowired DataSource dataSource) {        return new DataSourceTransactionManager(dataSource);    }}

 

3.2 编写业务逻辑

在业务逻辑层,我们可以通过DbTemplate执行数据库操作。例如,我们在UserService中使用ORM接口进行数据查询和操作:


 

 

java@Component@Transactionalpublic class UserService {    @Autowired    DbTemplate 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框架的功能,例如支持事务管理、连接池等。

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值