spring原生jdbcTemplate用起来有多爽

2 篇文章 0 订阅
1 篇文章 0 订阅


现在相比大部分的java开发工作者连接数据库最多的就是使用hibernate和mybatis,直到前段时间我接触到了某些大佬的项目,发现jdbcTemplate真的很好用。

分析

从最开始,我就对hibernate和mybatis非常的不满,但是奈何水平有限,没办法自己开发一个框架,无奈用着mybatis。我个人认为:
hibernate框架,开发简单,自动生成sql,甚至可以自动生成表结构。虽然简单,但是正因为如此,我根本不知道它给我生成的代码是什么样的。虽然有createQuery()可以自定义sql查询,但是update和delete就很难受,需要先自定义sql查询出来,再根据id执行update和delete,这可太呆了。
mybatis框架,最难受的是需要写xml,这可太难受了,我要是数据库有变化,还得更新一下数据库,再更新一下对象类,再更新一下xml,这可太难受了。虽然说有mybatis-plus可以自定义稍复杂的sql,但是再复杂一点的sql,什么join、with子表之类的,似乎也不太行。

我就想能即不写对象字段和数据库字段对应的xml,也不写对代码侵入行比较强的注解,而且用起来非常简单,执行的时候,能清楚的直到每一步在干什么,没有内部自己搞一堆事情,同时能自己写sql提高sql编写能力。有没有这样的?原本我觉得肯定没有啊,我要求这么多。现在,我总于发现了:spring原生jdbcTemplate。

使用方式

需要亿点开发

第一步,直接就开始开发JdbcTemplateProxy

public class JdbcTemplateProxy {
    private final JdbcTemplate jdbcTemplate;

    public JdbcTemplateProxy(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

	// 这个方法的作用,同xml文件中对象字段和数据库字段对应的代码
    public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
        return new NamedParameterJdbcTemplate(getJdbcTemplate());
    }

	// 这个方法主要用于判断要执行的sql查询是简单对象还是自定义的bean,因为自定义对象的查询需要有属性映射,不太一样
    private <T> boolean isPrim(Class<T> clazz) {
        return clazz == String.class || clazz == Byte.class || clazz == Short.class || clazz == Integer.class
                || clazz == Long.class || clazz == Float.class || clazz == Double.class || clazz == Character.class
                || clazz == Boolean.class;
    }

	// 这里写一些自定义方法,下文讲到
}

原生的jdbcTemplate虽好,但易用性当然是不高的啦,为了让它变得易用,自己写一个jdbcTemplateProxy类,封装了jdbcTemplate,包含所有jdbcTemplate原生特性,并能够自定义一些方法,高度灵活。能够干自定义什么方法呢?

    /**
     * 查询对象, 直接以对象做参数
     */
    public <T> T queryForObject(String sql, Object param, Class<T> clazz) {
        if (isPrim(clazz)) {
            return this.getNamedParameterJdbcTemplate()
                    .queryForObject(sql, new MyBeanPropertySqlParameterSource(param), clazz);
        } else {
            return this.getNamedParameterJdbcTemplate()
                    .queryForObject(sql, new MyBeanPropertySqlParameterSource(param),
                            BeanPropertyRowMapper.newInstance(clazz));
        }
    }
    /**
     * 查询对象, 自定义map参数
     */
    public <T> T queryForObject(String sql, Map<String, ?> param, Class<T> clazz) {
        if (isPrim(clazz)) {
            return this.getNamedParameterJdbcTemplate().queryForObject(sql, new MyMapSqlParameterSource(param), clazz);
        } else {
            return this.getNamedParameterJdbcTemplate()
                    .queryForObject(sql, new MapSqlParameterSource(param), BeanPropertyRowMapper.newInstance(clazz));
        }
    }
    /**
     * 查询列表, 以对象做参数
     */
    public <T> List<T> queryForList(String sql, Object param, Class<T> clazz) {
        if (isPrim(clazz)) {
            return this.getNamedParameterJdbcTemplate()
                    .queryForList(sql, new MyBeanPropertySqlParameterSource(param), clazz);
        } else {
            return this.getNamedParameterJdbcTemplate()
                    .query(sql, new MyBeanPropertySqlParameterSource(param), BeanPropertyRowMapper.newInstance(clazz));
        }
    }
    /**
     * 查询列表, 自定义map参数
     */
    public <T> List<T> queryForList(String sql, Map<String, ?> param, Class<T> clazz) {
        if (isPrim(clazz)) {
            return this.getNamedParameterJdbcTemplate().queryForList(sql, new MyMapSqlParameterSource(param), clazz);
        } else {
            return this.getNamedParameterJdbcTemplate()
                    .query(sql, new MapSqlParameterSource(param), BeanPropertyRowMapper.newInstance(clazz));
        }
    }
    /**
    * 更新, 对象做参数
    */
    public <T> void update(String sql, T params) {
        SqlParameterSource paramSource = new MyBeanPropertySqlParameterSource(params);
        this.getNamedParameterJdbcTemplate().update(sql, paramSource);
    }
    /**
    * 更新, 自定义map做参数
    */
    public void update(String sql, Map<String, ?> params) {
        this.getNamedParameterJdbcTemplate().update(sql, new MyMapSqlParameterSource(params));
    }
    /**
    * 批量更新, 对象做参数
    */
    public <T> void batchUpdate(String sql, List<T> list) {
        SqlParameterSource[] paramSource = this.createBatch(list.toArray());
        this.getNamedParameterJdbcTemplate().batchUpdate(sql, paramSource);
    }
    /**
    * 更新, 自定义map做参数
    */
    public <V> void batchUpdate(String sql, Map<String, V>[] list) {
        SqlParameterSource[] paramSource = this.createBatch(list);
        this.getNamedParameterJdbcTemplate().batchUpdate(sql, paramSource);
    }

这是最常用的,还可以自定义更多的定制化方法。参数:

  • sql,自己写的sql语句
  • param,查询参数
  • clazz,查询结果的对象类(这就等于是写了Mapper.xml了)

有什么好处呢
比如有一个User对象:user,你想查id=user.id的User或者name=user.name的User,你可以使用框架或者写两个方法如下:

selectById(String id)
selectByName(String name)

而现在,则不然,现在调用以对象作为参数的queryForObject()是这样:

selectById(User user)
selectByName(User user)

查User对象,不管是以什么查询,查询的参数都可以是User对象,只是根据sql不同,会自动匹配对象中的属性作为参数,降低了代码的耦合程度。当然你要是想id作为参数,也可以用以自定义map作为参数的queryForObject()。

第二步,配置Datasource和JdbcTemplateProxy

@Configuration
public class DataSourceConfig {
    @Bean(name = "oracleDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid")
    public DataSource oracleDataSource() {
        return new DruidDataSource();
    }

    @Bean("oracleJdbcTemplateProxy")
    public JdbcTemplateProxy oracleJdbcTemplateProxy() {
        DataSource oracleDatasource = oracleDataSource();
        return new JdbcTemplateProxy(oracleDatasource);
    }
}

用起来

使用起来是这样的(以查询一个对象为例):

// 注入proxy
@Resource(name = "oracleJdbcTemplateProxy")
private JdbcTemplateProxy proxy;

public User queryById(String id) {
	String sql = "select id, name from user where id = :id";
	Map<String, String> param = new HashMap<>();
	param.put("id", id);
	proxy.queryForObject(sql, param, User.class);
}

不用写xml,不用写注解,无代码侵入,sql自定义,方法可复用,多种参数可选,灵活性高。刚开始使用的时候感觉这什么玩意儿,搞这么一堆,后来,发现是真的舒服,简单易用不说,开发的时候,比较复杂的sql,能够debug看sql和参数,别提多高效。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值