JDBC进阶 元数据
1:resultSet
当创建一个ResultSet时,你可以设置三个属性:
类型
ResultSet.TYPE_FORWARD_ONLY
该常量指示光标只能向前移动的 ResultSet 对象的类型。
ResultSet.TYPE_SCROLL_INSENSITIVE
该常量指示可滚动但通常不受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。
ResultSet.TYPE_SCROLL_SENSITIVE
该常量指示可滚动并且通常受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。
并发
ResultSet.CONCUR_READ_ONLY
该常量指示不可以更新的 ResultSet 对象的并发模式。
ResultSet.CONCUR_UPDATABLE
该常量指示可以更新的 ResultSet 对象的并发模式。
可保存性
ResultSet.HOLD_CURSORS_OVER_COMMIT
该常量指示提交当前事务时,具有此可保存性的打开的 ResultSet 对象将保持开放。
ResultSet.CLOSE_CURSORS_AT_COMMIT
该常量指示提交当前事务时,具有此可保存性的打开的 ResultSet 对象将被关闭。
在创建Statement或PreparedStatement时已经设置了这些值,如下所示:
Statement statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT
); PreparedStatement statement = connection.prepareStatement(sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT
);
1.1最基本的ResultSet.
最基本的ResultSet是因为,这个ResultSet他起到的作用就是完成了查询结果的存储功能,而且只能读去一次,不能够来回的滚动读取. 最常用的
1.2 可滚动的ResultSet类型
next(),previous(), first(),last() 移动绝对行 absolute(int n),移动相对行relative(int n),
ResultSet.TYPE_FORWARD_ONLY
只能向前滚动
ResultSet.TYPE_SCROLL_INSENSITIVE
实现任意的前后滚动, 对于修改不敏感
Result.TYPE_SCROLL_SENSITIVE
实现任意的前后滚动, 对于修改敏感.
1.3 可更新的ResultSet
ResultSet对象可以完成对数据库中表的修改,但是我知道ResultSet只是相当于数据库中表的视图,所以并不时所有的ResultSet只要设置了可更新就能够完成更新的,能够完成更新的ResultSet的SQL语句必须要具备如下的属性: 通过 并发下面属性设置
a,只引用了单个表.
b,不含有join或者group by子句.
c,那些列中要包含主关键字.
执行顺序UpdatXXX 更新操作执行必须执行
:moveToInsertRow() 是把ResultSet移动到插入行 这个插入行是表中特殊的一行
moveToCurrentRow() 移动到插入行 如果之前Insert,那么就移动到之前Insert()0哪一行,没有Insert 就没有效果
:UpdateXXX()
:insertRow()
1.4 可保持的ResultSet
所有的Statement的查询对应的结果集是一个,如果调用Connection的commit()方法也会关闭结果集.
通过设置 HOLD_CURSORS_OVER_COMMIT 来保持数据
2:PrepareStatement
特点: 禁止了拼接SQL可以注入的现象,将会SQL传入数据库编译通过设置参数方式保证安全性
select * from user where name='aa' and password='bb' or 1=1 //类始于这种SQL的注入方式
2.1: 基本操作
executeQuery() 执行查询
executeUpdate() 执行CUD操作
execute() 执行DDL操作
executeLargeUpdate() 执行超大SQL语句
String sql = "select * from user";
PreparedStatement preparedStatement = connection.prepareStatement(sql); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) {
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String birthday = resultSet.getString("birthday");
String sex = resultSet.getString("sex");
String address = resultSet.getString("address"); System.out.println(" " + username + " " + birthday + " " + sex
+ " " + address);
}
2.2 复用pststemetn
即为一次创建多次使用, 通过connection创建prepareStatement 多次使用 prepareStatement
特点 参数可以变,但是SQl 是不变的
PreparedStatement preparedStatement = connection.prepareStatement(sql);//创建prepareStatement preparedStatement.setString(,"Fant.J");
preparedStatement.setInt(,);
int result = preparedStatement.executeUpdate(); // 第一次使用 preparedStatement.setString(,"Fant.J reUseTest");
preparedStatement.setInt(,);
preparedStatement.executeUpdate();//第二次使用 但是都是用的第一次创建ps 时的编译语句
2.3 性能分析
PreparedStatement是Statement的子类,区别:
PreparedStatement 编译一次,可以将多条SQL语句汇聚到一起执行,提高执行效率
Statement 是每一条SQL执行一次,100条SQL 就要执行100次
两个级别的复用:
JDBC驱动程序重新使用PreparedStatement。
数据库重用PreparedStatement。
3:执行批量SQL
用到 addBatch()和executeBatch()方法 用于 Insert Update Delete 等SQL的处理
3.1: statemet 方式
Statement statement = null;
try{
statement = connection.createStatement(); statement.addBatch("update people set firstname='aaa' where id=123");
statement.addBatch("update people set firstname='bbb' where id=456");
statement.addBatch("update people set firstname='ccc' where id=789"); int[] recordsAffected = statement.executeBatch(); // 返回每个SQl执行后影响的元组数
} finally {
if(statement != null) statement.close();
}
3.2: preparedstatement 方式
String sql = "update user set username=? where id=?";
PreparedStatement preparedStatement = null;
try{
preparedStatement =connection.prepareStatement(sql); preparedStatement.setString(, "aaa");
preparedStatement.setLong (, );
preparedStatement.addBatch(); preparedStatement.setString(, "bbb");
preparedStatement.setLong (, );
preparedStatement.addBatch(); int[] affectedRecords = preparedStatement.executeBatch();// 返回每条语句执行影响的行数
}finally {
if(preparedStatement != null) {
preparedStatement.close();
}
}
4: 事物transaction
对出现异常的SQL代码进行回退(可能系统异常),保证数据一致性
4.1 基本处理
Connection connection = ...
try{
connection.setAutoCommit(false); // 这种处理方式 没有回滚点 出错将返回整个SQL代码
// create and execute statements etc.
connection.commit();
} catch(Exception e) {
connection.rollback();
} finally {
if(connection != null) {
connection.close();
}
}
4.2 断点事物处理
Connection conn = JdbcUtils.getConnection();
PreparedStatement ps = null;
Savepoint savepoint=null; //断点
try {
conn.setAutoCommit(false);
savepoint = conn.setSavepoint(); //设置当前断点1 当然可以有多个断点
ps = conn.prepareStatement("update account set balance = balance - ? where name=?");
ps.setInt(, );
ps.setString(, "Jack");
ps.executeUpdate();
//出现异常
System.out.println( / );
//给 rose 加钱
ps = conn.prepareStatement("update account set balance = balance + ? where name=?");
ps.setInt(, );
ps.setString(,"Rose");
ps.executeUpdate();
//提交事务
conn.commit();
System.out.println("转账成功");
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback(savepoint);
} catch (Exception e1) {
e1.printStackTrace();
}
}finally {
JdbcUtils.close(conn, ps);
}
}
5 存储过程
DELIMITER // # 分割符号 默认是; 在多条语句时候需要进行改变
DELIMITER // # 分割符号 默认是; 在多条语句时候需要进行改变
CREATE PROCEDURE findStuById(IN pid INTEGER)
BEGIN
SELECT * FROM student WHERE id=pid;
END //
DELIMITER ;
通过Call关键字调用储存过程 CallableStatement处理存储过程 PreparedStatement ==处理DML DML DQL
@Test
public void test_producer() throws SQLException {
Connection conn = JdbcUtils.getConnection();
CallableStatement call = conn.prepareCall("CALL findStuByID(?)"); call.setInt(, );
ResultSet resultSet = call.executeQuery();
Student student=null;
while(resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
boolean gender = resultSet.getBoolean("gender");
Date birthday = resultSet.getDate("birthday");
student= new Student(id, name, gender, birthday);
}
System.out.println(student);
}
6 元数据类型
6.1 DatabaseMetaData 数据库元数据
数据库基本信息
Connection conn = JdbcUtils.getConnection(); DatabaseMetaData metaData = conn.getMetaData(); int majorVersion = metaData.getDatabaseMajorVersion();
String productVersion = metaData.getDatabaseProductVersion();
String driverName = metaData.getDriverName();
String url = metaData.getURL();
String userName = metaData.getUserName();
System.out.println(majorVersion);//8
System.out.println(productVersion);//8.0.13
System.out.println(driverName);//MySQL Connector/J
System.out.println(url);//jdbc:mysql://127.0.0.1:3306/day
System.out.println(userName);//root@localhost
数据库所有信息的获取
getTableTypes() 方法 可以使用正则表达式
Connection conn = JdbcUtils.getConnection();
DatabaseMetaData metaData = conn.getMetaData();
//
String catalog = "day"; //对应数据库名称
String schemaPattern = "*"; // mysql没有这个概念 sql server对应用户名称操作权限
String tableNamePattern = "student"; // 对应数据库名称
String[] types = {"TABLE"}; // 数据库中具体的类型 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。 ResultSet result = metaData.getTables(
catalog, schemaPattern, tableNamePattern, types ); while(result.next()) {
String catalogName = result.getString(1);
String schemaName = result.getString(2);
String tableName = result.getString(3);
String columName = result.getString(6);
System.out.println(tableName);
System.out.println(catalogName);
System.out.println(columName);
}
在表中列出列 getColumS()
Connection conn = JdbcUtils.getConnection();
DatabaseMetaData metaData = conn.getMetaData();
//
String catalog = "day"; // 对应数据库名称
String schemaPattern = "*"; // mysql没有这个概念 sql server对应用户名称操作权限
String tableNamePattern = "student"; // 对应数据库名称
String columnNamePattern = null; ResultSet result = metaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); while (result.next()) {
String columName = result.getString(4);// 列名称
String data_type = result.getString(5);// 列类型
System.out.println(columName);
System.out.println(data_type);
}
主键信息
getPrimaryKeys() 获取主键信息
getExportedKeys() 获取外键信息
Connection conn = JdbcUtils.getConnection();
DatabaseMetaData metaData = conn.getMetaData();
//
String catalog = "day"; //执行库
String schemaPattern = null; // mysql为null
String tableNamePattern = "student"; ResultSet result = metaData.getPrimaryKeys(catalog, schemaPattern, tableNamePattern);
metaData.getExportedKeys(catalog, schema, table)
while (result.next()) {
String tablename = result.getString(3);// 表名
String keyname = result.getString(4);//主键名
System.out.println(tablename);
System.out.println(keyname);
6.2 ParameterMetaData 参数元数据类型
对于传递的SQL中的参数(占位符? )的个数 数据进行处理
前提:
增加 &generateSimpleParameterMetadata=true
所有的参数认为是字符串(VARCHAR)类型
注意:ParameterMetaData许多方法MySQL并不友好支持,比如像获取指定参数的SQL类型的getParameterType方法,如果数据库驱动连接URL只是简单的“jdbc:mysql://localhost:3306/jdbcdemo”那么MyEclipse会抛出SQLException异常,必须要将URL修改为“jdbc:mysql://localhost:3306/jdbcdemo?generateSimpleParameterMetadata=true”才行。但是像getParameterType等等与其他的方法也没多好用,因为如下面的例子,这些方法好像只会将所有的参数认为是字符串(VARCHAR)类型
public void test_ParameterINFO() throws SQLException {
Connection conn = JdbcUtils.getConnection();
String sql="SELECT * FROM STUDENT WHERE id=?";
PreparedStatement preparedStatement = conn.prepareStatement(sql); ParameterMetaData pMetaData = preparedStatement.getParameterMetaData();
preparedStatement.setInt(1, 1); int count = pMetaData.getParameterCount();
for(int i = 1; i <= count; i ++) {
System.out.print(pMetaData.getParameterClassName(i) + "\t");
System.out.print(pMetaData.getParameterType(i) + "\t");
System.out.println(pMetaData.getParameterTypeName(i));
}
//执行查询操作
preparedStatement.executeQuery();
//执行查询操作
ResultSet rs = preparedStatement.executeQuery(); while(rs.next()) {
System.out.println(rs.getInt("id") + "\t"
+ rs.getString("name") + "\t" + rs.getBoolean("gender")
+ "\t" + rs.getDate("birthday"));
}
}
6.3 ResultSetMetaData 结果集元数据
通过 ResultSet.getMetaData();获取 ,主要对于表中的一些列进行获取,处理
Connection conn = JdbcUtils.getConnection(); String sql="SELECT * FROM STUDENT WHERE id=?";
PreparedStatement pStatement = conn.prepareStatement(sql); pStatement.setInt(1, 1);
ResultSet reSet = pStatement.executeQuery(); ResultSetMetaData metaData = reSet.getMetaData(); int count = metaData.getColumnCount(); for (int i = 1; i <= count; i++) {
String columnClassName = metaData.getColumnClassName(i);//类型
String columnName = metaData.getColumnName(i);//列名
int columnType = metaData.getColumnType(i);//列属性值
String typeName = metaData.getColumnTypeName(i);//列类型名
String label = metaData.getColumnLabel(i);//列名
System.out.println(columnClassName+"\t"+columnName+"\t"+columnType+"\t"+typeName+"\t"+label);
}
JDBC进阶 元数据的更多相关文章
- day16(jdbc进阶,jdbc之dbUtils)
1.jdbc进阶 jdbc事务管理 jdbc中的事务管理其实就是交给了连接对象去管理.先写一个简单的事务管理 public class Demo01 { private static Connecti ...
- MYSQL 之 JDBC(十): JDBC的元数据
可以从Connection对象中获得有关数据库管理系统的各种信息 获取这些信息的方法都是在DatabaseMetaData类中. DatabaseMetaData:描述数据库的元数据对象 Result ...
- JDBC进阶
PreparedStatement的使用: conn = DriverManager.getConnection("jdbc:mysql://localhost/mydata?" ...
- Apache kylin进阶——元数据篇
一.Apache kylin元数据的存储 Apache kylin的元数据包括 立方体描述(cube description),立方体实例(cube instances)项目(project).作业( ...
- JDBC进阶之PreparedStatement执行SQL语句(MySQL)
一.什么是PreparedStatement 参阅Java API文档,我们可以知道,PreparedStatement是Statement的子接口(如图所示),表示预编译的 SQ ...
- JDBC 进阶:使用封装通用DML DQL 和结构分层以及at com.mysql.jdbc.PreparedStatement.setTimestamp空指针异常解决
准备: 数据表 CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(10) DEFAULT ...
- jdbc详解(三)
开源数据库连接池 l 现在很多 WEB 服务器 ( Weblogic , WebSphere , Tomcat) 都提供了 DataSoruce 的实现,即连接池的实现.通常我们把 DataSourc ...
- JDBC学习DayTwo
一.利用反射及JDBC元数据编写通用的查询方法 1.ResultSetMetaData 定义:描述ResultSet的元数据对象,即从中可以获取到结果集中有多少列.列名是什么. 获取 ResultSe ...
- ref:Spring JDBC框架
ref:https://blog.csdn.net/u011054333/article/details/54772491 Spring JDBC简介 先来看看一个JDBC的例子.我们可以看到为了执行 ...
随机推荐
- Python语法速查: 7. 函数基础
返回目录 (1)函数基本 ● 函数是第一类对象 Python中万物皆对象,所有对象都是第一类的(first class),函数也不例外,也是第一类对象.既然是对象,那就可以当作普通的对象数据处理,比如 ...
- s3c2440裸机-代码重定位(2.编程实现代码重定位)
代码重定位(2.编程实现代码重定位) 1.引入链接脚本 我们上一节讲述了为什么要重定位代码,那么怎么去重定位代码呢? 上一节我们发现"arm-linux-ld -Ttext 0 -Tdata ...
- 花了三个月终于把所有的 Python 库全部整理了!可以说很全面了
库名称简介 Chardet字符编码探测器,可以自动检测文本.网页.xml的编码. colorama主要用来给文本添加各种颜色,并且非常简单易用. Prettytable主要用于在终端或浏览器端构建格式 ...
- 第04组 Beta冲刺(1/4)
队名:斗地组 组长博客:地址 作业博客:Beta冲刺(1/4) 各组员情况 林涛(组长) 过去两天完成了哪些任务: 1.分配展示任务 2.收集各个组员的进度 3.写博客 展示GitHub当日代码/文档 ...
- MongoDB数据库常用SQL命令 — MongoDB可视化工具Robo 3T
1.db.collection.updateMany() 修改集合中的多个文档. db.getCollection('user').find({"pId":"3332a5 ...
- plantuml-绘制状态图和活动图和部署图
背景 状态图:对象的所有状态,以及基于事件发生的状态改变的过程: 活动图:用例的工作流程: 部署图:系统的软硬件物理体系结构: 状态图 基本语法 元素 语法 说明 开始和结束状态 [*] 标识开始和结 ...
- (转)深入解析TensorFlow中滑动平均模型与代码实现
本文链接:https://blog.csdn.net/m0_38106113/article/details/81542863 指数加权平均算法的原理 TensorFlow中的滑动平均模型使用的是滑动 ...
- docker tomcat8 mysql8部署常见错误
出现docker: out of memory bug ,内存溢出 解决方法: free -mh 应该看一下内存 内存优化/买内存 出现java.util.zip.ZipException: erro ...
- 实时同步sersync实战
目录 实时同步sersync实战 什么是实时同步 sersync和rsync+inotify对比 sersync项目实战 安装rsync的服务端(backup) NFS服务端部署sersync 实时同 ...
- 41-data-packed volume container
在上一节的例子中 volume container 的数据归根到底还是在 host 里,有没有办法将数据完全放到 volume container 中,同时又能与其他容器共享呢? 当然可以,通常我们称 ...