JDBC(三):数据库元数据以及JDBCTemplate的基本使用

1. 数据库元数据

1.1 概述

元数据用来描述数据中的库结构、表结构、记录信息的数据

1543288379135

1.2 分类
三种元数据说明以及获得方式
数据库元数据用来描述数据库信息:数据库使用版本,数据库使用驱动等。如何得到数据库元数据对象呢?通过Connection对象可以得到。
参数元数据 ParameterMetaData描述SQL语句中各种参数:占位符个数,每个参数的数据类型。 通过PreparedStatement对象可以得到参数元数据对象
结果集元数据描述结果集:结果集有多少列,每列数据是什么类型等信息。 通过ResultSet对象可以得到参数元数据对象

ParameterMetaData接口中的方法

//通过预编译语句对象得到一个参数元数据对象
ParameterMetaData getParameterMetaData()
//得到 SQL 语句中占位符个数
int getParameterCount() 
//得到指定占位符的数据类型,智能
//参数param:指定第几个占位符
String getParameterTypeName(int param) 
-- MySQL 驱动对参数元数据的数据类型支持不理想 ,需要如下配置才能得到的参数的 MySQL 数据类型,而且只能得到 VARCHAR 类型 ,如果不配置这个参数则会出现异常。
jdbc:mysql://localhost:3306/ 数据 库名?generateSimpleParameterMetadata=true

ResultSetMetaData 接口中的方法

//得到结果集中一共有多少列
int getColumnCount() 
//得到指定列的列名
String getColumnName(int column)
//得到指定列的数据类型名字
String getColumnTypeName(int column)

使用

/**
 * 使用结果集元数据对象
 */
public class DemoResult {
    public static void main(String[] args) throws SQLException {
        //创建连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql:///day20", "root", "root");
        //创建预编译语句对象
        PreparedStatement ps = conn.prepareStatement("SELECT id,name from student");
        //执行查询语句
        //得到结果集
        ResultSet rs = ps.executeQuery();
        //得到结果集元数据
        ResultSetMetaData metaData = rs.getMetaData();
        //调用元数据的方法
        //得到一共有多少列

        System.out.println("结果集中一共有" + metaData.getColumnCount() + "列");
        //得到指定列的列名
        System.out.println("第 2 列的列名:" + metaData.getColumnName(2));
        //得到指定列的数据类型
        System.out.println("第 1 列的数据类型:" + metaData.getColumnTypeName(1));
        //关闭
        rs.close();
        ps.close();
        conn.close();
    }
}
1.3 自定义框架

可以通过元数据对JDBC进行封装,使JDBC更加容易使用。

案例需求:
修改 DruidUtils 工具类,使用元数据做一个通用的增删改的方法。

druid.properties配置文件

url=jdbc:mysql://localhost:3306/day19
username=root
password=awsed2zx
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
maxWait=2000

DruidUtils工具类

package com.zmysna.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class DruidUtils {
    private static DataSource ds;
	/**
		加载配置文件,初始化DataSource
	*/
    static {
        Properties pro = new Properties();
        try {
            pro.load(DruidUtils.class.getResourceAsStream("/druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
	
    /**
    	用元数据实现的通用增删改方法
    */
    public static int update(String sql, Object...params)  {
        try (
            //得到连接对象
            Connection conn = getConnection();
            //创建预编译语句对象,有占位符
            PreparedStatement ps = conn.prepareStatement(sql);) {

            //通过参数元数据得到一共有多少个占位符
            ParameterMetaData pmd = ps.getParameterMetaData();
            int count = pmd.getParameterCount();
            //使用循环来替换每个占位符
            for (int i = 0; i < count; i++) {
                ps.setObject((i + 1), params[i]);
            }
            //更新操作
            return ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }


    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    public static void close(Connection conn, Statement statement, ResultSet rs) {
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(Connection conn, Statement statement) {
        close(conn, statement,null);
    }
}

2. JDBCTemplate

JdbcTemplate就是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。使用JdbcTemplate编程我们只需要做以下步骤:

  • 提供SQL语句

  • 提供占位符的真实值(可选)

2.1 使用步骤
  • 导包

在这里插入图片描述

  • 执行DML语句
public int update(final String sql, Object…args)    
作用:执行增删改的操作
参数:
1) 要执行的SQL语句
2) 替换占位符的值
返回值:影响的行数
package com.zmysna;

import com.itheima.utils.DataSourceUtils;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 使用模板对象实现增删改操作
 */
public class Demo2DML {
    //1)	创建JdbcTemplate对象,传入数据源对象。
    JdbcTemplate template = new JdbcTemplate(DataSourceUtils.getDataSource());

    //a)	向表中添加5条记录
    @Test
    public void testInsert() {
        template.update("INSERT INTO student values(null,?,?,?)", "孙悟空", 1, "2000-11-11");
        template.update("INSERT INTO student values(null,?,?,?)", "孙悟天", 1, "2000-11-11");
        template.update("INSERT INTO student values(null,?,?,?)", "孙悟饭", 1, "2000-11-11");
        template.update("INSERT INTO student values(null,?,?,?)", "牛魔王", 1, "2000-11-11");
        template.update("INSERT INTO student values(null,?,?,?)", "白骨精", 0, "2000-11-11");
    }

    //b)	修改编号为2的学生名字和生日
    @Test
    public void testUpdate() {
        int i = template.update("UPDATE student SET name=?, gender=?,birthday=? where id=?", "蜘蛛精", 0, "1985-10-02", 2);
        System.out.println(i);
    }

    //c)	删除编号为5的记录
    @Test
    public void testDelete() {
        int i = template.update("DELETE FROM student where id=?", 5);
        System.out.println(i);
    }
}
  • 执行DQL语句

    • 查询一条记录封装成Map对象
    Map<String,Object> queryForMap(String sql, Object…args)
    参数:
    1) 要查询的SQL语句
    2) 占位符的真实值
    返回值: 一条记录,封装成Map对象。可以用于多表连接,可以查询一张表中几列。
    注:如果查询的结果集没有记录,会抛出异常
    

    练习:

    
    import com.itheima.utils.DataSourceUtils;
    import org.junit.Test;
    import org.springframework.jdbc.core.JdbcTemplate;
    
    import java.util.Map;
    
    /**
     * 使用模板对象执行DQL语句
     */
    public class Demo3DQL {
    
        //创建模板对象
        JdbcTemplate template = new JdbcTemplate(DataSourceUtils.getDataSource());
    
        //查询一条记录,封装成Map对象
        @Test
        public void testQueryForMap() {
            // 使用JdbcTemplate对象的queryForMap()方法查询结果
            Map<String, Object> map = template.queryForMap("SELECT * from student where id=?", 2);
            // 返回一个Map对象,并且输出结果。
            System.out.println(map);
            // 如果没有查询到结果会怎么样? 会出现异常
        }
    }
    
    
    • 查询一条记录,封装成一个实体类对象
    <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args)	
    参数:
    1) 要执行的SQL语句
    2) 这是一个接口,需要我们实现它,并且重写里面的方法,实现将一条结果集封装成一个实体类对象。
    3) 占位符的真实值
    返回值: 封装好的实体类对象,如果没有找到结果,会抛出异常。
    
    //RowMapper接口中只有一个mapRow方法,需要重写, 可以使用其实现类BeanPropertyRowMapper。
    T mapRow(ResultSet rs, int rowNum) throws SQLException	作用: 用于将查询到的结果集封装成一个对象
    参数:
    1) 从数据库中查询到的结果集,有可能是一条记录,也可能是多条记录
    2) 行号,从0开始编号,表示当前这条记录在整个结果集中是第几行。
    返回值: 封装好的对象
    
    //BeanPropertyRowMapper类的构造方法
    public BeanPropertyRowMapper(Class<T> mappedClass)
    通过构造方法创建一个行映射对象,参数是:指定是的类型,如:Student.class,Employee.class   
    

    练习

    //使用JdbcTemplate对象的queryForObject ()方法查询结果,方法中传入一个接口的匿名内部类
    @Test
    public void testQueryForObject() {
        Student student = template.queryForObject("select * from student where id=?", new RowMapper<Student>() {
            @Override
            public Student mapRow(ResultSet rs, int i) throws SQLException {
                Student student = new Student();
                //封装所有的属性
                student.setId(rs.getInt("id"));
                student.setName(rs.getString("name"));
                student.setGender(rs.getBoolean("gender"));
                student.setBirthday(rs.getDate("birthday"));
                return student;
            }
        }, 1);
        System.out.println(student);
    }
    	
    //使用RowMapper的实现类BeanPropertyRowMapper查询结果
    @Test
    public void testQueryForObject2() {
        Student student = template.queryForObject("select * from student where id=?", new BeanPropertyRowMapper<>(Student.class), 2);
        System.out.println(student);
    }
    
    • 查询多条记录封装成List<Map<String,Object>>
    List<Map<String, Object>> queryForList(String sql, Object…args)
    参数:
    1) 要执行的SQL语句
    2) 替换占位符的真实值
    返回值: 一个封装好List<Map<String,Object>>
    如果没有记录:返回List,没有元素。不会出现异常,也不为null。
    

    练习

    @Test
    public void testQueryForList() {
        List<Map<String, Object>> list = template.queryForList("SELECT * from student where gender=?", 1);
        //输出每一条记录
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }
    
    • 查询多条记录封装成List
    List<T> query(String sql, RowMapper<T> rowMapper, Object... args)
    参数:
    1) 要执行的SQL语句
    2) 行映射接口,传它的子类BeanPropertyRowMapper
    3) 替换占位符的真实值
    返回值:封装好的List集合,如果没有记录,集合中没有元素,不为NULL。
    

    练习

    @Test
    public void testQuery() {
        List<Student> students = template.query("select * from student where gender=?", new BeanPropertyRowMapper<>(Student.class), 1);
        for (Student student : students) {
            System.out.println(student);
        }
    }
    
    • 查询1条记录:聚合函数
    public <T> T queryForObject(String sql, Class<T> requiredType, Object... args)
    参数:
    1)	要执行的SQL语句
    2)	指定返回的类型,如:int.class
    3)	替换占位符的真实值
    返回值: 指定类型的值
    

    练习

    @Test
    public void testQueryForObject3() {
        int count = template.queryForObject("select count(*) from student where gender=?", int.class, 1);
        System.out.println("男生人数:" + count);
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值