jjzjj

day14-JdbcTemplate

liyuelian 2023-04-16 原文

JdbcTemplate

看一个实际需求:

如果希望使用spring框架做项目,Spring框架如何处理对数据库的操作呢?

  • 方案一:使用之前的JdbcUtils类

  • 方案二:spring提供了一个操作数据库(表)的功能强大的类JdbcTemplate。我们可以通过ioc容器来配置一个JdbcTemplate对象,使用它来完成对数据库表的各种操作。

1.基本介绍

JdbcTemplate APIs:下载的文档-spring-5.3.8-dist\spring-framework-5.3.8\docs\javadoc-api\index.html

  1. 通过Spring可以配置数据源,从而完成对数据表的操作
  2. JdbcTemplate 是 spring 提供的访问数据库的技术。可以将 JDBC 的常用操作封装为模板方法。

2.使用实例

需求说明:使用 Spring 的方式来完成 JdbcTemplate 配置和使用

一、搭建环境:

  1. 引入JdbcTemplate 需要的jar包(Spring5)

  2. 创建数据库spring和表monster

-- 创建数据库
CREATE DATABASE spring;
USE spring;
-- 创建表monster
CREATE TABLE monster(
id INT PRIMARY KEY,
`name` VARCHAR(64) NOT NULL DEFAULT '',
skill VARCHAR(64) NOT NULL DEFAULT ''
)CHARSET=utf8;
INSERT INTO monster VALUES(100,'青牛怪','吐火');
INSERT INTO monster VALUES(200,'黄袍怪','吐烟');
INSERT INTO monster VALUES(300,'蜘蛛怪','吐丝');

二、配置DataSource

  1. 创建配置文件src/jdbc.properties(key值随意)

在spring的ioc容器中,可以通过属性文件给bean注入值

jdbc.user=root
jdbc.pwd=123456
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
  1. 创建容器配置文件src/JdbcTemplate_ioc.xml
<!--引入外部的属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据源对象-DataSource-->
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
    <!--给数据源对象配置属性值-->
    <property name="user" value="${jdbc.user}"/>
    <property name="password" value="${jdbc.pwd}"/>
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
</bean>
  1. 测试连接
@Test
public void testDatasourceByJdbcTemplate() throws SQLException {
    //获取容器
    ApplicationContext ioc = 
        new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //因为 ComboPooledDataSource实现了 DataSource接口,这里使用接口类型来获取对象
    DataSource dataSource = ioc.getBean(DataSource.class);
    Connection connection = dataSource.getConnection();
    System.out.println("获取到连接connection=" + connection);
    connection.close();
}

成功连接:

  1. 配置 JdbcTemplate_ioc.xml,将数据源分配给 JdbcTemplate bean对象
<!--配置JdbcTemplate对象-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
    <!--给JdbcTemplate对象配置DataSource属性-->
    <property name="dataSource" ref="dataSource"/>
</bean>

2.1添加数据

@Test
public void addDataByJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //获取JdbcTemplate对象
    JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);
    
    //1.添加方式
    String sql = "insert into monster values(400,'红孩儿','风火轮')";
    jdbcTemplate.execute(sql);
    
    //2.添加方式 2(推荐)
    String sql2 = "insert into monster values(?,?,?)";
    //返回的 int类型 表示执行后表受影响的记录数
    int affected = jdbcTemplate.update(sql2, 500, "牛魔王", "芭蕉扇");
    System.out.println("add ok affected = " + affected);
}

添加成功:

2.2修改数据

//测试通过JdbcTemplate对象完成修改数据
@Test
public void updateDataByJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    
    //获取JdbcTemplate对象
    JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);
    
    String sql = "update monster set skill=? where id=?";
    int affected = jdbcTemplate.update(sql, "美人计", 300);
    System.out.println("update is ok, affected = " + affected);
}

修改成功:

2.3批量处理

对于某个类,如果有很多API,使用的步骤:

1.先确定API名字 2.根据API提供的参数,组织参数 3.根据API可以推测类似的用法和功能

//批量添加两个 monster
@Test
public void addBatchDataByJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");

    //获取JdbcTemplate对象
    JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);

    //1.准备参数
    String sql = "insert into monster values(?,?,?)";
    List<Object[]> batchArgs = new ArrayList<>();
    batchArgs.add(new Object[]{600, "白蛇", "翻江倒海"});
    batchArgs.add(new Object[]{700, "青蛇", "竹叶青"});

    //2.调用
    //int[] batchUpdate(String sql, List<Object[]> batchArgs);
    //说明:返回结果为int数组,每个元素对应上面的sql语句对表的影响记录数
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);

    //输出
    for (int anInt : ints) {
        System.out.println("anInt=" + anInt);
    }
    System.out.println("batch add is ok..");
}

批处理结果:

2.4查询

实体类 Monster.java

package com.li.bean;

/**
 * @author 李
 * @version 1.0
 * Javabean / Entity
 */
public class Monster {
    private Integer monsterId;
    private String name;
    private String skill;

    //无参构造器一定要有,spring底层反射创建对象时需要使用
    public Monster() {
    }

    //全参构造器
    public Monster(Integer monsterId, String name, String skill) {
        this.monsterId = monsterId;
        this.name = name;
        this.skill = skill;
    }

    public Integer getMonsterId() {
        return monsterId;
    }

    public void setMonsterId(Integer monsterId) {
        this.monsterId = monsterId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "monsterId=" + monsterId +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                '}';
    }
}

2.4.1查询单行多列

查询 id=500 的 monster 并封装到 Monster 实体对象

//查询 id=100的 monster并封装到 Monster实体对象
@Test
public void selectDataByJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //获取JdbcTemplate对象
    JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);

    //1.确定API
    //<T> T queryForObject(String sql, RowMapper<T> rowMapper, @Nullable Object... args)
    
    //2.准备参数
    //注意:封装对象时,如果查询返回的字段名和实体对象的属性名不一致会出现问题,最好使用别名!
    String sql = "SELECT id AS monsterId , NAME, skill FROM monster WHERE id=?";
    //使用RowMapper接口来对返回的数据,进行一个封装(底层是反射->setter)
    RowMapper<Monster> rowMapper = new BeanPropertyRowMapper<>(Monster.class);
    
    //3.调用
    Monster monster = jdbcTemplate.queryForObject(sql, rowMapper, 500);
    System.out.println("monster=" + monster);
}

查询结果:

2.4.2查询多行多列

查询 id>=200 的 monster,并封装到 Monster 实体对象

//查询 id>=200的 monster并封装到 Monster实体对象
@Test
public void selectMulDataByJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //获取JdbcTemplate对象
    JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);

    //1.确定API
    //public <T> T query(String sql, ResultSetExtractor<T> rse, @Nullable Object... args)
    //2.组织参数
    String sql = "SELECT id AS monsterId , NAME, skill FROM monster WHERE id>= ?";
    BeanPropertyRowMapper<Monster> rowMapper = new BeanPropertyRowMapper<>(Monster.class);

    List<Monster> query = jdbcTemplate.query(sql, rowMapper, 200);
    for (Monster monster : query) {
        System.out.println("monster=" + monster);
    }
}

查询结果:

2.4.3查询单行单列

查询返回结果只有单行单列的值,比如查询表中的总记录数,或者查询 id=200 的 name 字段的值

//查询 id>=200的 monster并封装到 Monster实体对象
@Test
public void selectScalarByJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //获取JdbcTemplate对象
    JdbcTemplate jdbcTemplate = ioc.getBean(JdbcTemplate.class);

    //1.确定API
    // public <T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args)
    //requiredType 表示返回的单行单列的 值的 数据类型

    //2.组织参数
    String sql = "SELECT NAME FROM monster WHERE id=?";
    String sql2 = "SELECT COUNT(*) FROM monster";
    //3.调用
    String name = jdbcTemplate.queryForObject(sql, String.class, 200);
    Integer count = jdbcTemplate.queryForObject(sql2, Integer.class);
    System.out.println("id=200 的 name = " + name);
    System.out.println("monster表的总记录数 = " + count);
}

查询结果:

2.5具名参数

  • 什么是具名参数?

具名参数:SQL 按名称(以冒号开头)而不是按位置进行指定。具名参数更易于维护, 也提升了可读性。具名参数由框架类在运行时用占位符取代。

在 JDBC用法中,SQL参数是用占位符 ? 表示,并且受到位置的限制。定位参数的问题在于,一旦参数的位置发生变化,必须改变参数的绑定。

而在Spring JDBC中,绑定SQL参数的另一种选择是使用具名参数 (named parameter),SQL具名参数是按照名称绑定,而不是位置绑定。具名参数的命名随意。

2.5.1具名参数的使用

需求:使用map传入具名参数完成操作,比如添加 螃蟹精.:name 就是具名参数形式。

使用具名参数,需要使用 NamedParameterJdbcTemplate 类,语句形式 String sql = "insert into monster values(:my_id, :name, :skill)";

  1. 增加配置NameParameterJdbcTemplate对象(部分)
<!--配置NamedParameterJdbcTemplate对象-->
<bean class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate" id="namedParameterJdbcTemplate">
    <!--通过构造器设置数据源-->
    <constructor-arg name="dataSource" ref="dataSource"/>
</bean>
  1. 测试
@Test
public void testDataByNamedParameterJdbcTemplate() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //获取 NamedParameterJdbcTemplate对象
    NamedParameterJdbcTemplate namedParameterJdbcTemplate =
            ioc.getBean(NamedParameterJdbcTemplate.class);

    //1.确定API
    //public int update(String sql, Map<String, ?> paramMap)
    //2.准备参数 [:my_id,:name,:skill] 要求按照规定的名字来设置参数,具名参数的命名随意,但是map中的key要和命名一致
    String sql = "insert into monster values(:my_id,:name,:skill)";
    HashMap<String, Object> paramMap = new HashMap<>();
    //给map填入具体的数据
    paramMap.put("my_id", 800);
    paramMap.put("name", "孙悟空");
    paramMap.put("skill", "七十二变");
    //3.调用
    int affected = namedParameterJdbcTemplate.update(sql, paramMap);
    System.out.println("add is ok , affected = " + affected);

}

插入成功:

2.5.1sqlparametersource

使用 sqlparametersource 来封装具名参数,添加一个Monster

//sqlparametersource 的使用
@Test
public void operaDataBySqlparametersource() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    //获取 NamedParameterJdbcTemplate对象
    NamedParameterJdbcTemplate namedParameterJdbcTemplate =
            ioc.getBean(NamedParameterJdbcTemplate.class);

    //1.确定API
    // public int update(String sql, SqlParameterSource paramSource)
    //2.准备参数
    //注意这里的具名参数要和对象的属性名一致
    String sql = "insert into monster values(:monsterId,:name,:skill)";
    Monster monster = new Monster(900, "乌鸡精", "吃人不吐骨头");
    SqlParameterSource sqlParameterSource = new BeanPropertySqlParameterSource(monster);
    //3.调用
    int affected = namedParameterJdbcTemplate.update(sql, sqlParameterSource);
    System.out.println("add is ok , affected = " + affected);
}

添加成功:

2.5综合使用

在Dao对象中使用 JdbcTemplate完成对数据的操作

  1. MonsterDao
package com.li.jdbctemplate.dao;

import com.li.bean.Monster;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;

/**
 * @author 李
 * @version 1.0
 */
@Repository //将MonsterDao注入到spring容器
public class MonsterDao {
    //注入一个属性
    @Resource
    private JdbcTemplate jdbcTemplate;

    //完成保存任务
    public void save(Monster monster) {
        //组织 sql语句
        String sql = "insert into monster values(?,?,?)";
        int affected = jdbcTemplate.update
                (sql, monster.getMonsterId(), monster.getName(), monster.getSkill());
        System.out.println("affected=" + affected);
    }
}
  1. 容器文件中配置要扫描的包
<!--引入外部的属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据源对象-DataSource-->
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
    <!--给数据源对象配置属性值-->
    <property name="user" value="${jdbc.user}"/>
    <property name="password" value="${jdbc.pwd}"/>
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
</bean>

<!--配置JdbcTemplate对象-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
    <!--给JdbcTemplate对象配置DataSource属性-->
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--配置要扫描的包-->
<context:component-scan base-package="com.li.jdbctemplate.dao"/>
  1. 测试
//测试 MonsterDao 是否生效
@Test
public void monsterDaoSave() {
    //获取容器
    ApplicationContext ioc =
            new ClassPathXmlApplicationContext("JdbcTemplate_ioc.xml");
    MonsterDao monsterDao = ioc.getBean(MonsterDao.class);
    Monster monster = new Monster(1000, "哪吒", "混天绫");
    monsterDao.save(monster);
    System.out.println("MonsterDao 保存成功...");
}

插入成功:

有关day14-JdbcTemplate的更多相关文章

  1. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  2. ruby - 在 Ubuntu 14.04 中使用 Curl 安装 RVM 时出错 - 2

    我试图在Ubuntu14.04中使用Curl安装RVM。我运行了以下命令:\curl-sSLhttps://get.rvm.io|bash-sstable出现如下错误:curl:(7)Failedtoconnecttoget.rvm.ioport80:Networkisunreachable非常感谢解决此问题的任何帮助。谢谢 最佳答案 在执行curl之前尝试这个:echoipv4>>~/.curlrc 关于ruby-在Ubuntu14.04中使用Curl安装RVM时出错,我们在Stack

  3. ruby - gem install pg error : couldn't understand kern. osversion `14.0.0' on Yosemite w/Ruby 2.1.5 - 2

    我使用RVM安装Ruby-2.1.5并再次运行bundle。现在pggem不会安装,我得到这个错误:geminstallpg-v'0.17.1'----with-pg-config=/Applications/Postgres.app/Contents/Versions/9.3/bin/pg_configBuildingnativeextensionswith:'--with-pg-config=/Applications/Postgres.app/Contents/Versions/9.3/bin/pg_config'Thiscouldtakeawhile...ERROR:Error

  4. ruby-on-rails - rails : Find tasks that were created on a certain day? - 2

    我有一个任务列表(名称、starts_at),我试图在每日View中显示它们(就像iCal)。deftodays_tasks(day)Task.find(:all,:conditions=>["starts_atbetween?and?",day.beginning,day.ending]end我不知道如何将Time.now(例如“2009-04-1210:00:00”)动态转换为一天的开始(和结束),以便进行比较。 最佳答案 deftodays_tasks(now=Time.now)Task.find(:all,:conditio

  5. ruby-on-rails - Ubuntu 14.04 Rails 丢失文件 - 2

    安装Rails时,一切都很好,但后来,我写道:rails-v和输出:/home/toshiba/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in`require':cannotloadsuchfile--rails/cli(LoadError)from/home/toshiba/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in`r

  6. 什么是0day漏洞?如何预防0day攻击? - 2

    什么是0day漏洞?0day漏洞,是指已经被发现,但是还未被公开,同时官方还没有相关补丁的漏洞;通俗的讲,就是除了黑客,没人知道他的存在,其往往具有很大的突发性、破坏性、致命性。0day漏洞之所以称为0day,正是因为其补丁永远晚于攻击。所以攻击者利用0day漏洞攻击的成功率极高,往往可以达到目的并全身而退,而防守方却一无所知,只有在漏洞公布之后,才后知后觉,却为时已晚。“后知后觉、反应迟钝”就是当前安全防护面对0day攻击的真实写照!为了方便大家理解,中科三方为大家梳理当前安全防护模式下,一个漏洞从发现到解决的三个时间节点:T0:此时漏洞即0day漏洞,是已经被发现,还未被公开,官方还没有相

  7. 使用时 Rubygems 2.0.14 不是线程安全的 bundle 程序安装消息 - RUBYGEMS VERSION : 2. 4.5.1 - 2

    运行bundle安装时,我收到以下消息:Rubygems2.0.14isnotthreadsafe,soyourgemswillbeinstalledoneatatime.UpgradetoRubygems2.1.0orhighertoenableparallelgeminstallation.这很奇怪,因为在我的RubyGems环境中它说我的RubyGems版本是:2.4.5.1(见下文)~/w/Rafftopia❯❯❯gemenvRubyGemsEnvironment:-RUBYGEMSVERSION:2.4.5.1-RUBYVERSION:2.2.5(2016-04-26patc

  8. ruby - Rails 比较 date.end_of_day.to_datetime 和 date.to_datetime.end_of_day 返回的日期对象值时返回 false - 2

    ruby1.9.3dev(2011-09-23修订版33323)[i686-linux]轨道3.0.20最近为什么在与DateTimeonRails相关的RSpecs项目上工作我发现在给定日期以下语句发出的值date.end_of_day.to_datetime和date.to_datetime.end_of_day虽然它们表示相同的日期时间,但比较时返回false。为了确认这一点,我打开了Rails控制台并尝试了以下操作1.9.3dev:053>monday=Time.now.monday=>2013-02-2500:00:00+05301.9.3dev:054>monday.cla

  9. ruby - 在 Ubuntu 14.04 上使用 RVM 安装 Ruby 2.2.2 时出错 - 2

    这是什么。我首先做了:rvmgetstablervminstallruby-2.2.2没有交易。它向我展示了以下内容:$rvminstallruby-2.2.2Searchingforbinaryrubies,thismighttakesometime.Nobinaryrubiesavailablefor:ubuntu/14.04/i386/ruby-2.2.2.Continuingwithcompilation.Pleaseread'rvmhelpmount'togetmoreinformationonbinaryrubies.Checkingrequirementsforubunt

  10. ruby - 无法在 MacOS 10.14.2 Mojave : Error running '__rvm_make -j4' 上使用 RVM 安装任何 Ruby - 2

    将MacOS升级到10.14.2Mojave后,我无法再使用RVM安装任何Ruby版本。它总是给出这样的错误:$rvminstall2.5.3ruby-2.5.3-#removingsrc/ruby-2.5.3..Searchingforbinaryrubies,thismighttakesometime.Nobinaryrubiesavailablefor:osx/10.14/x86_64/ruby-2.5.3.Continuingwithcompilation.Pleaseread'rvmhelpmount'togetmoreinformationonbinaryrubies.Ch

随机推荐