前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >手写一个orm框架-7

手写一个orm框架-7

作者头像
何白白
发布于 2019-06-28 05:57:42
发布于 2019-06-28 05:57:42
50200
代码可运行
举报
运行总次数:0
代码可运行

手写一个orm框架-7

生成sql:select

上一篇讲了怎样生成一个sqlwhere的一部分,之后我们要做事情就简单很多了,就只要像最开始一样的生成各种sql语句就好了,之后只要再加上我们需要的条件,一个完整的sql就顺利的做好了。

现在我们开始写生成查询语句的sql。一个查询语句大致上是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT name, id, create_date, age, mark, status FROM user

这里可以看出来,一个基础的查询语句基本上就是一个 SELECT 后面加上需要查询的字段,跟上 FROM 和要查询的表名称就好了。 最多后面可能需要加上 ORDER BY/GROUP BY/LIMIT ….之类的就好了,因为比较简单,这里就不写了。(太复杂的就直接写sql就好了,我自己不需要这种操作)

思路

  1. 从之前拿到的映射关系中拿到属性和字段名的映射,然后拼接sql。
  2. 执行sql,并取出结果。
  3. 实例化class,使用反射给class的属性赋值。

这几步都还是比较好做的,第一步很简单,仿照着之前写的就可以了。因为这里在执行sql的时候,我使用的是JdbcTemplate,这里有一个不大不小的坑,下面我说一下。

一个不大不小的坑

这个坑是我在使用我写好的这个项目给公司做报表的时候碰到的。原因是这样,因为数据库中有些字段是datetime类型的,这个字段有时候在表中的值是:0000-00-00 00:00:00,(我也不知道这个值是怎么进去的,但是就是存在/(ㄒoㄒ)/~~)但是这个值是无法转换成为java中的Date类型。所以这里会报错。

我在这里写了一个继承SpringJdbc中的ColumnMapRowMapper的类,是这样的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.jdbc.core.ColumnMapRowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 捕获取值的错误
 *
 * @author hjx
 */
public class PlusColumnMapRowMapper extends ColumnMapRowMapper {

    /**
     * 数据库类型为时间时, 如果值为 0000-00-00 00:00:00
     * 会报错,所以重写此方法,返回null
     *
     * @param rs
     * @param index
     * @return
     * @throws SQLException
     */
    @Override
    protected Object getColumnValue(ResultSet rs, int index) throws SQLException {
        Object columnValue = null;
        try {
            columnValue = super.getColumnValue(rs, index);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return columnValue;

    }
}

这个类具体在哪里使用,会在下面说明。

实现

现在说一下怎么实现上面的思路,首先因为第一步比较简单,就不写了。我直接从第二步开始。

  1. 执行sql,并取出结果。 这里我用的是JdbcTemplate的方法,这给我们提供了一个方法: <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper) 这里前两个参数比较好理解,一个是sql,一个是sql中的参数。第三个是需要传一个接口**RowMapper**,这个接口具体是干啥的上网一查就知道了~~~ 这里面有一个方法: T mapRow(ResultSet rs, int rowNum) throws SQLException 第一个参数是查询的结果,第二个是指现在在第几行结果,返回值是你要返回什么对象。这里我们需要重写这个方法,把查询出的结果转换成为我们需要的对象。我们可以这么写: /** * 把数据库查询的结果与对象进行转换 * * @param resultSet * @param rowNum * @return * @throws SQLException */ @Override public T mapRow(ResultSet resultSet, int rowNum) throws SQLException { Map<String, Object> resultMap = columnMapRowMapper.mapRow(resultSet, rowNum); 。。。。 这个方法中的columnMapRowMapper 就是上面我们写的PlusColumnMapRowMapper,它的作用就是将查询结果第 rowNum 拿出来,并且将结果转换过成为一个 Map<String, Object>。其中: key :是表字段名称。 Object :该字段的值。 上面写的PlusColumnMapRowMapper主要作用就是在获取值的时候如果发生异常,返回一个null。 在这一步里我们已经拿到了执行sql的结果,现在我们要将结果转换过为我们需要的class。
  2. 将结果转换为class 在上一步我们拿到了存放结果Map,现在只需要将map遍历一下,然后实例化java对象,根据字段和属性的映射关系使用反射将属性一个个的set进去就好了。现在贴上上一步的完整代码: public T mapRow(ResultSet resultSet, int rowNum) throws SQLException { Map<String, Object> resultMap = columnMapRowMapper.mapRow(resultSet, rowNum); T instance = getInstance(tableClass); for (Map.Entry<String, Object> entry : resultMap.entrySet()) { //数据库字段名 String key = entry.getKey(); if (!columnFieldMapper.containsKey(key)) { continue; } Field declaredField = columnFieldMapper.get(key); if (declaredField == null) { continue; } //数据库字段值 Object value = entry.getValue(); setFieldValue(instance, declaredField, value); } return instance; } 其中 columnFieldMapper 是一个Map<String, Field>key是表的字段个名称。value是对应的class的属性。 下面是 setFieldValue的具体代码: boolean setFieldValue(T t, Field field, Object value) { field.setAccessible(true); try { if (value != null) { field.set(t, value); return true; } } catch (IllegalAccessException e) { e.printStackTrace(); } return false; } 这样,就可以将查询出的结果根据映射关系转换成为我们需要的class了。

其他的

如果查询需要添加条件的话,可以使用之前讲的 生成条件的工具将条件的sql拼接在这里的sql后面,相应的,where里的参数也要按照顺序添加进数组就好了。

相同的,如果要添加 ORDER BY/GROUP BY/LIMIT这些东西的话也是一样的操作。主要还是要看自己的代码是怎么设计的了。我自己用的只写了ORDER BYLIMIT 。可以在我的github上找到。地址在这里:https://github.com/hjx601496320/JdbcPlus 。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
分布式分析引擎Kylin Spring DataSource封装
Apache Kylin™是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc. 开发并贡献至开源社区。它能在亚秒内查询巨大的Hive表。
高广超
2019/03/20
9290
分布式分析引擎Kylin Spring DataSource封装
聊聊spring jdbc的RowMapper
spring-jdbc-4.3.10.RELEASE-sources.jar!/org/springframework/jdbc/core/RowMapper.java
code4it
2018/09/17
1.5K0
半个小时手写一个极简版ORM框架,实现简单的CRUD操作
ORM框架可以减轻在开发中的一些负担,简单的单表的增删改查如果全部都写sql的话那么也会是一个工作量,因为不仅要面临写大量的sql语句, 还要处理jdbc结果集映射到实体的操作,这其中会面临写大量重复无用的代码,而且在结果集映射的过程中出错的可能性也很大,所以就出现了 很多ORM框架,例如Mybatis,Hibernate等,对于简单的单表的操作,这些框架提供了大量的API给我们使用,大大的减轻开发的负担,本文 就实现一个简单版的ORM框架,让大家理解ORM的实现思路。
小四的技术之旅
2022/07/26
8180
半个小时手写一个极简版ORM框架,实现简单的CRUD操作
SpringBoot高级篇JdbcTemplate之数据查询下篇
环境依然借助前面一篇的配置,链接如: 190407-SpringBoot高级篇JdbcTemplate之数据插入使用姿势详解
一灰灰blog
2019/05/26
2.3K0
JAVA实现DAO基本层CRUD操作
随着shh2各种操作方便框架。越来越多JAVA WEB效率,可是,假设在不了解这些框架使用的场合的情况下,一拿到项目就盲目地选择这些框架进行系统架构的搭建,就有可能造成非常多不是必需的资源浪费。
全栈程序员站长
2022/07/05
1.1K0
搞懂钩子方法和模板方法,看完这篇就够了
通常的模板方法模式中会设计一个abstract的抽象方法,交给它的子类实现,这个方法称为模板方法。而钩子方法,是对于抽象方法或者接口中定义的方法的一个空实现,也是模板方法模式的一种实现方式。
玖柒的小窝
2021/11/07
3270
搞懂钩子方法和模板方法,看完这篇就够了
通常的模板方法模式中会设计一个abstract的抽象方法,交给它的子类实现,这个方法称为模板方法。而钩子方法,是对于抽象方法或者接口中定义的方法的一个空实现,也是模板方法模式的一种实现方式。
Tom弹架构
2021/11/07
1.5K0
SpringBoot高级篇JdbcTemplate之数据查询上篇
环境依然借助前面一篇的配置,链接如: 190407-SpringBoot高级篇JdbcTemplate之数据插入使用姿势详解
一灰灰blog
2019/05/26
3.8K0
【Java】已解决:org.springframework.jdbc.LobRetrievalFailureException LOB检索失败异常
在使用Spring Framework进行数据库操作时,开发者可能会遇到org.springframework.jdbc.LobRetrievalFailureException的报错问题。该异常通常发生在从数据库中检索大对象(LOB)数据(如BLOB或CLOB)时。典型的场景包括从数据库中读取大文本字段或二进制数据。
屿小夏
2024/09/10
530
手写一个orm框架-4
在上一篇里,我们已经取到了我们在生成sql语句中所需要的信息,这一篇里我们开始根据class来生成我们需要的sql。在这之前我们先确认几件事情
何白白
2019/06/28
5290
30个类手写Spring核心原理之自定义ORM(下)(7)
EntityOperation主要实现数据库表结构和对象类结构的映射关系,代码如下:
Tom弹架构
2021/12/17
5440
JdbcTemplate学习笔记(更新插入删除等)
4、使用JdbcTemplate进行查询时,使用queryForXXX()等方法 
bear_fish
2018/09/19
1.3K0
SpringJDBC源码解析
至此Deno工程搭建完毕,有需要源码的同学可以从下方地址获取 https://github.com/shiyujun/spring-framework
Java学习录
2019/08/28
1.1K0
SpringJDBC源码解析
利用反射及JDBC元数据编写通用的查询方法
遇到了若干问题: 1.从oracle返回的列名都是大写,再用反射,就找不到相对应得 名字 2.oracle 中number类型 返回来,就变成了BigDecimal public static void main(String[] args){ String sql = "SELECT IDCARD , examcard , " + "studentname ," + "lacation LoCATIO
用户1503405
2021/09/22
4940
Spring StoredProcedure Cursor 使用
(1)Java StoredProcedure 中定义in,out参数的顺序要与SP sql中定义的in,out参数顺序一致
全栈程序员站长
2022/09/18
3690
Incorrect result size: expected 1, actual 2
结果大小不正确:预期为1,实际为0(Incorrect result size: expected 1, actual 0) 字符串的Jdbctemplate查询:EmptyResultDataAccessException:结果大小不正确:expected 1,actual 0(Jdbctemplate query for string: EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0)
猫头虎
2024/04/07
2360
JDBC 利用反射及 JDBC 元数据编写通用的查询方法(7)
public class MyTest { public static void test01() throws ClassNotFoundException, SQLException, IllegalAccessException, InstantiationException { String driverClass = "com.mysql.jdbc.Driver"; String jdbcUrl = "jdbc:mysql://localhost:3306/
桑鱼
2020/03/17
3700
手写一个orm框架-6
上一篇里我们实现了生成insert的sql,下面要开始实现update,delete,select的sql语句了。但是这些语句有一个比较麻烦的地方是:它们一般后面都会有where条件,因为在执行的时候不能把表里所有的数据都进行操作。
何白白
2019/06/28
4800
java通过cglib动态生成实体bean
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/130975.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/01
5230
Spring JDBC-使用Spring JDBC访问数据库
Spring JDBC是Spring所提供的持久层技术,它的主要目的降低JDBC API的使用难度,以一种更直接、更简洁的方式使用JDBC API。
小小工匠
2021/08/17
1.3K0
推荐阅读
相关推荐
分布式分析引擎Kylin Spring DataSource封装
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文