JDBC学习DayTwo
一、利用反射及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的更多相关文章
- JDBC学习笔记(2)——Statement和ResultSet
Statement执行更新操作 Statement:Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句.Statement ...
- JDBC学习笔记(1)——JDBC概述
JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据库连接. JDBC库中所包含的API任务通常与数据库使用: 连接到数 ...
- 【转】JDBC学习笔记(2)——Statement和ResultSet
转自:http://www.cnblogs.com/ysw-go/ Statement执行更新操作 Statement:Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数 ...
- 【转】JDBC学习笔记(1)——JDBC概述
转自:http://www.cnblogs.com/ysw-go/ JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据 ...
- jdbc学习总结
jdbc学习总结: 一.简介: jdbc,直译为java连接数据库.实际为java为很好的操作数据库而提供的一套接口,接口的实现(即驱动)由各个数据库厂商提供. 二.知识要点: 连接5要素,3 ...
- JDBC 学习笔记(十一)—— JDBC 的事务支持
1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...
- JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架
1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...
- JDBC 学习笔记(六)—— PreparedStatement
1. 引入 PreparedStatement PreparedStatement 通过 Connection.createPreparedStatement(String sql) 方法创建,主要用 ...
- JDBC学习笔记二
JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...
随机推荐
- video 自动循环播放
video 只加autoplay并不能自动播放,需要再加上muted <video controls="controls" autoplay loop muted> ...
- 小账本APP——软件项目风险管理及解决办法案例
小账本APP——软件项目风险管理及解决办法案例 摘要 软件项目风险是指在软件开发过程中遇到的预算和进度等方面的问题以及这些问题对软件项目的影响.软件项目风险会影响项目计划的实现,如果项目风险变成现实, ...
- WSGI协议主要包括server和application两部分:
WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端:WSGI application接收由server ...
- linux日常使用指令总结
linux 日常指令总结(ubuntu): ls -lha 所有文件及权限 df -h 系统磁盘空间 du -sh 当前目录大小 du -ah --max-depth=1 显示目录下所有的文件和文件夹 ...
- Adobe Photoshop安装
Photoshop cc2018安装 Adobe 软件套装已不再以 (Creative Suite) CS命名,而是改成 (Creative Cloud) CC,主推云服务!Adobe CC 套装中总 ...
- Java语言中的奇淫技巧
variable length parameter list(可变长度参数列表) 很久之前了解过有这么一种写法,但转眼即忘.今天在公司项目的代码里看到,有点小惊讶,写这代码的同事还是有点水平的...
- 菜鸡学C语言之寻根溯源
题目描述 Mogg最近翻了翻自己家的族谱,想康康祖先是谁.但是族谱因为年久失修太乱了,他现在只整理出来了一系列父子关系,你能帮他找一找直系亲属中辈分最大的一位吗?(即父亲的父亲的父亲……) 输入 第1 ...
- ORACLE中RECORD、VARRAY、TABLE的使用详解(转)
原文地址:ORACLE中RECORD.VARRAY.TABLE的使用详解
- 【问题记录】MyBatis查询数据库返回多个不同类型参数的结果集的接收方式
其实是个非常简单的问题,但是这玩意儿弄得我很难受,又浪费了一个下午的时间,简直了…… 问题大概是,我在查询数据库时,查询的结果有两个,一个是varchar格式的字段,一个int格式字段,例如: sel ...
- [luogu P3313] [SDOI2014]旅行
[luogu P3313] [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神 ...