一、利用反射及JDBC元数据编写通用的查询方法

1.ResultSetMetaData

定义:描述ResultSet的元数据对象,即从中可以获取到结果集中有多少列、列名是什么。

获取 ResultSetMetaData 对象:

  调用 ResultSet 的 getMetaData() 方法

方法:

  int getColumnCount():SQL语句中包含的列数

  String getColumnLabel(int column):获取指定的列的别名,其中索引从1开始

2.通用的查询方法

    /**
* 通用的查询方法:可以根据传入的SQL、Class对象返回SQL对应的对象
*
* @param clazz:
* 描述对象的类型
* @param sql:
* SQL语句,可能带占位符
* @param args:
* 填充占位符的可变参数
*/
public <T> T get(Class<T> clazz, String sql, Object... args) {
T entity = null; Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null; try {
// 1.获得ResultSet对象
conn = getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery(); // 2.得到ResultSetMetaData对象
ResultSetMetaData rsmd = rs.getMetaData(); // 3.创建一个Map<String, Object>对象,键:SQL查询的列的别名;值:列的值
Map<String, Object> values = new HashMap<>(); // 4.处理结果集,利用ResultSetMetaData填充3对应的Map对象
if (rs.next()) {
for (int i = 0; i < rsmd.getColumnCount(); i++) {
String columnLabel = rsmd.getColumnLabel(i + 1);
Object columnValue = rs.getObject(i + 1); values.put(columnLabel, columnValue);
}
} // 5.若Map不为空集,利用反射创建 clazz 对应的对象
if (values.size() > 0) {
entity = clazz.newInstance(); // 6.遍历Map对象,利用反射为Class对象的对应的属性赋值。
for (Map.Entry<String, Object> entry : values.entrySet()) {
String fieldName = entry.getKey();
Object value = entry.getValue();
setFieldValue(entity, fieldName, value);
}
} } catch (Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
} return entity;
}
    /**
* 利用反射给具体对象的属性赋值
*/
public void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Class<? extends Object> clazz = obj.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}

使用该通用方法:

    /**
* 使用通用的查询方法
*/
public void testGet(){
String sql = "select id, name, email, birth "
+ "from customers where id = ?";
Customer customer = get(Customer.class, sql, 5);
System.out.println(customer);
}

二、DAO设计模式

1.定义:

  DAO即 Data Access Object ,访问数据信息的类,包含了对数据的CRUD(create, read, update, delete),而不包含任何业务相关的信息。

2.作用:

  实现功能的模块化,更有利于代码的保护和升级。

3.方法:

void update(String sql, Object ... args); //INSERT,UPDATE,DELETE操作都可以包含在其中

    // INSERT,UPDATE,DELETE操作都可以包含在其中
public void update(String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null; try {
conn = JDBCTools.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ps.executeUpdate(); } catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.releaseDB(ps, null, conn);
}
}
public class JDBCTools {
public static void releaseDB(Statement stat, ResultSet rs, Connection conn){
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} public static Connection getConnection() throws Exception{
// 1.准备连接数据库的基本信息
String driver = null;
String jdbcUrl = null;
String user = null;
String password = null;
// 读取类路径下的jdbc.properties文件
InputStream in = JDBCTools.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(in);
driver = properties.getProperty("driver");
jdbcUrl = properties.getProperty("jdbcUrl");
user = properties.getProperty("user");
password = properties.getProperty("password"); // 2.加载数据库驱动程序(对应的Driver实现类中有注册驱动的静态代码块)
// DriverManager
// .registerDriver(Class.forName(driverClass).newInstance));
Class.forName(driver);
// 3.通过DriverManager的getConnection()方法 获取数据库连接
Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
return conn;
}
}

<T> T get(Class<T> calzz, String sql, Object ... args); //查询一条记录,返回对应的对象

    // 查询一条记录,返回对应的对象
public <T> T get(Class<T> clazz, String sql, Object... args) {
List<T> result = getForList(clazz, sql, args);//查询多条记录的方法
if(result.size() > 0){
return result.get(0);
}
return null;
}

<T> List<T> getForList(Class<T> clazz, String sql, Object ... args); //查询多条记录,返回对应的对象的集合

    // 查询多条记录,返回对应的对象的集合
public <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
List<T> list = new ArrayList<>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.得到结果集
conn = JDBCTools.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
//2.处理结果集,得到Map的List,其中一个Map对象对应一条记录
List<Map<String, Object>> values = handleResultSetToMapList(rs);
//3.把Map的List转为clazz对应的List
list = transferMapListToBeanList(clazz, values); } catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.releaseDB(ps, rs, conn);
}
return list;
} /**
* 将Map对应的List转换为clazz对应的List
* @param clazz
* @param values
* @return
* @throws Exception
*/
private <T> List<T> transferMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values)
throws Exception {
List<T> result = new ArrayList<T>();
T bean = null; if (values.size() > 0) {
for (Map<String, Object> m : values) {
bean = clazz.newInstance();
for (Map.Entry<String, Object> entry : m.entrySet()) {
String fieldName = entry.getKey();
Object value = entry.getValue();
JdbcTest.setFieldValue(bean, fieldName, value);
}
result.add(bean);
}
}
return result;
} /**
* 处理结果集,得到Map的一个List,其中一个Map对象代表一条记录
*
* @param rs
* @return
* @throws SQLException
*/
private List<Map<String, Object>> handleResultSetToMapList(ResultSet rs) throws SQLException {
List<String> columnLabels = getColumnLabels(rs);
List<Map<String, Object>> values = new ArrayList<>();
Map<String, Object> map = null;
while (rs.next()) {
map = new HashMap<>();
for (String label : columnLabels) {
Object ColumnValue = rs.getObject(label);
map.put(label, ColumnValue);
}
values.add(map);
}
return values;
} /**
* 获取结果集的ColumnLabel(列的别名) 对应的List
*
* @param rs
* @return
* @throws SQLException
*/
private List<String> getColumnLabels(ResultSet rs) throws SQLException {
List<String> labels = new ArrayList<>();
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
labels.add(rsmd.getColumnLabel(i + 1));
}
return labels;
}

<E> E getForValue(String sql, Object ... args); //返回某条记录的某一个字段的值或者一个统计的值(统计一共有多少条记录等)

    // 返回某条记录的某一个字段的值或者一个统计的值(统计一共有多少条记录或最大的值等)
public <E> E getForValue(String sql, Object... args) {
// 得到结果集:该结果集应该只有一行,且只有一列
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCTools.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
if (rs.next()) {
return (E) rs.getObject(1);
} } catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.releaseDB(ps, rs, conn);
}
return null;
}

4.使用Beanutils工具类操作JavaBean

  JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,通过getter和setter方法来定义属性的get和set方法。

  可以通过一个apache的开源工具包 beanutils 来操作Java类的属性。

  要先导入commons-logging包和commons-beanutils包到类路径下。

  方法:setProperty(Object bean, String name, Object value):给对象bean的名字为name的属性赋value的值

       getProperty(Object bean, String name):返回对象bean的名为name的属性的值

  实例:

    public void BeanutilsTest() throws Exception{
Object obj = new Customer();
System.out.println(obj);
//Customer [id=0, name=null, email=null, birth=null]
BeanUtils.setProperty(obj, "id", "123");
System.out.println(obj);
//Customer [id=123, name=null, email=null, birth=null]
Object value = BeanUtils.getProperty(obj, "id");
System.out.println(value);//
}

  注:上面DAO的方法中利用反射给对象的属性赋值都可以换成beanutils的方法来赋值

//JdbcTest.setFieldValue(entity, fieldName, value);
BeanUtils.setProperty(entity, fieldName, value);

三、JDBC的元数据

1.DataBaseMetaData

  是在Connection对象上获得的(DataBaseMetaData dbmd = connnection.getMetaData()),DataBaseMetaData类的对象实现了获得有关数据库管理系统的各种信息的方法 ,包括数据库的各个表,表中的各个列,数据类型,触发器,存储方面等各方面信息。

2.ResultSetMetaData

  是在ResultSet对象上获得的,实现了获得结果集的列数和列的别名等方法。

四、处理Blob

1.定义:

  LOB,即Large Objects(大对象),是用来存储大量的二进制和文本数据的一种数据类型(一个LOB字段可以存储多达4GB的数据)

2.分类:

  内部LOB:

    BLOB(二进制数据)

    CLOB(单字节字符数据)

    NCLOB(多字节字符数据)

  CLOB和NCLOB适合存储超长的文本数据。BLOB适合处理大量的二进制数据,如图像,视频,音频,文件等。

  外部LOB:

    BFILE

  BFILE的数据是只读的,不参与事务。可帮助用户管理大量的由外部程序访问的文件。

3.实例:

    /**
* 插入Blob类型的数据必须用PreparedStatement,因为Blob类型的数据无法使用字符串拼写
*/
public void testInsertBlob() {
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCTools.getConnection();
String sql = "INSERT INTO customers (NAME, EMAIL, BIRTH,PICTURE) " + "VALUES(?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "AAA");
ps.setString(2, "abc@163.com");
ps.setDate(3, new Date(new java.util.Date().getTime()));
InputStream is = new FileInputStream("123.jpg");
ps.setBlob(4, is);
// 2)调用executeUpdate(sql)
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.releaseDB(null, ps, conn);
}
}

JDBC学习DayTwo的更多相关文章

  1. JDBC学习笔记(2)——Statement和ResultSet

    Statement执行更新操作 Statement:Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句.Statement ...

  2. JDBC学习笔记(1)——JDBC概述

    JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据库连接. JDBC库中所包含的API任务通常与数据库使用: 连接到数 ...

  3. 【转】JDBC学习笔记(2)——Statement和ResultSet

    转自:http://www.cnblogs.com/ysw-go/ Statement执行更新操作 Statement:Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数 ...

  4. 【转】JDBC学习笔记(1)——JDBC概述

    转自:http://www.cnblogs.com/ysw-go/ JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据 ...

  5. jdbc学习总结

    jdbc学习总结:   一.简介: jdbc,直译为java连接数据库.实际为java为很好的操作数据库而提供的一套接口,接口的实现(即驱动)由各个数据库厂商提供.   二.知识要点: 连接5要素,3 ...

  6. JDBC 学习笔记(十一)—— JDBC 的事务支持

    1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...

  7. JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架

    1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...

  8. JDBC 学习笔记(六)—— PreparedStatement

    1. 引入 PreparedStatement PreparedStatement 通过 Connection.createPreparedStatement(String sql) 方法创建,主要用 ...

  9. JDBC学习笔记二

    JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...

随机推荐

  1. 进程部分(IPC机制及生产者消费者模型)和线程部分

    进程部分 一:进程间通信IPC机制:由于进程之间的内存空间是相互隔离的,所以为了进程间的通信需要一个共享的内存空间, 但是共享带来的问题是数据在写的时候就不安全了,所以需要一种机制既有能共享的内存 空 ...

  2. AT2412 最大の和

    传送门 思路: 线段树暴力枚举区间,查询最大区间和. Code: #include<iostream> #include<cstdio> #include<algorit ...

  3. c++ std::advance

    // advance example #include <iostream> // std::cout #include <iterator> // std::advance ...

  4. dvi接口介绍

    Most graphics cards and motherboards feature a Digital Video Interface (DVI) connector for connectin ...

  5. Shiro框架配置-applicationContext里面的(仅提供借鉴)

    <!-- 配置自定义realm --> <bean id="shiroAuthRealm" class="com.sykj.realm.ShiroAut ...

  6. 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)

    A Drawing Borders 很多构造方法,下图可能是最简单的了 代码: #include<bits/stdc++.h> using namespace std; ; struct ...

  7. JavaScript如何生成思维导图(mindmap)

    JavaScript如何生成思维导图(mindmap) 一.总结 一句话总结:可以直接用gojs gojs 二.一个用JavaScript生成思维导图(mindmap)的github repo(转) ...

  8. [大数据面试题]storm核心知识点

    1.storm基本架构 storm的主从分别为Nimbus.Supervisor,工作进程为Worker. 2.计算模型 Storm的计算模型分为Spout和Bolt,Spout作为管口.Bolt作为 ...

  9. LeetCode--032--最长有效括号(java)

    给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 示例 1: 输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()&quo ...

  10. python 装饰器问题及解决方式

    #统计函数运行时间 import time #装饰器 def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() fun ...