一、利用反射及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. python基础知识点(unittest)

    目录: unittest 单元测试框架 1.写用例: Testcase 2.执行:TestSuite 类 TestLoader 类 3.比对结果(期望值/实际值):断言函数 4.结果:TestText ...

  2. 【转】Appium如何定位安卓APP元素

    转载原文:https://www.jianshu.com/p/efe9dcf8bbaf 一.定位工具 在安装appium环境的时候我们已经安装了SDK,里面就自带有元素定位的工具,位置在.../sdk ...

  3. java.lang.ClassNotFoundException: org.apache.log4j.Logger 异常

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'd ...

  4. UML图概述

    UML图概述 UML是一种分析设计语言,即一种建模语言.UML是由图形符号表达的建模语言,其结构主要包括视图.图.模型元素和通用机制四部分. UML包括5种视图,分别是用户视图.结构视图.行为视图.实 ...

  5. web api 安全

    这方面的文章已经有很多了,我只是记录一下自己在项目中应用的具体实现 客户端 DateTime t = DateTime.Now; long timeStamp = SignHelper.Convert ...

  6. jemter分布式部署及linux下分布式脚本执行

    jmeter进行接口性能测试,占用内存较大,在模拟千万计并发用户时,使用分布式部署进行分压测试. 操作步骤:选择一台机器作为调度机,其他机器作为执行机 一.jmeter分布式部署 前提条件:A.执行机 ...

  7. C++(实验二)

    实验结论 1.函数重载编程练习: 编写重载函数add(),实现对int型,double型,Complex型数据的加法.在main( )函数中定义不同类型 数据,调用测试. #include <i ...

  8. 字体图标库 IcoMoon IconFont Font Awesome的使用

    在项目开发的过程中,我们会经常用到一些图标.但是我们在使用这些图标时,往往会遇到失真的情况,而且图片数量很多的话,页面加载就越慢.所以,我们可以使用字体图标的方式来显示图标,字体图标任意放大缩小不会失 ...

  9. CentOS 7 + MySql 中文乱码解决方案

    原文:https://blog.csdn.net/qq_32953079/article/details/54629245,亲测有效,故记录之. 一.登录MySQL查看用SHOW VARIABLES ...

  10. js 实用小技巧

    https://blog.csdn.net/www93111/article/details/76176771