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的例子.我们可以看到为了执行 ...
随机推荐
- Centos7 基于SVN+Apache+IF.svnadmin实现web管理
1.简单介绍: iF.SVNAdmin应用程序是您的Subversion授权文件的基于Web的GUI.它基于PHP 5.3,需要安装一个Web服务器(Apache).该应用程序不需要数据库后端或任何类 ...
- mysql研究跟进
count(1)对比 count(*) count(N),N指的是列的序列号,innodb引擎下一般为主键列:count(*),mysql优化器也会将统计列自动优化.所以日常使用区别不大 阿里规范里的 ...
- 桶排序(C语言)
#include <stdio.h> int main(void) { int arr[5]={2,5,1,3,3}; //定义需要排序的数组 int res[6]={0}; //初始化& ...
- pytorch 中的Variable一般常用的使用方法
Variable一般的初始化方法,默认是不求梯度的 import torch from torch.autograd import Variable x_tensor = torch.randn(2, ...
- 【python之路.一】基础
数学操作符 数据类型 字符串复制(*复制次数int).连接(+) 该类操作只能同为字符串类型,否则需要强制转换类型 变量名规则 (驼峰式变量名&下划线式均可) # 注释 BIF(built-i ...
- Goland安装
Goland安装 http://c.biancheng.net/view/6124.html
- java之对象类型转换
基本数据类型之间的转换: 自动类型转换:小的数据类型可以自动转换成大的数据类型: 强制类型转换:可以把大的数据类型转换成小的数据类型:float = (float)32.0; public class ...
- Blazor入坑指南
一 为什么用Blazor 原本就是后端程序员, 技术栈基于C#, 懂一点前端jQuery/Html 不管是webAssembly还是ServerSide, 就是想方便地做单页应用, 能wasm自然更好 ...
- asp.net MVC通用权限管理系统-响应式布局-源码
一.Angel工作室简单通用权限系统简介 AngelRM(Asp.net MVC Web api)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术 ...
- Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类
因为Jdk7及以前的日期时间类的不方便使用问题和线程安全问题等问题,2005年,Stephen Colebourne创建了Joda-Time库,作为替代的日期和时间API.Stephen向JCP提交了 ...