JDBC是一套标准(接口),用来连接关系型数据库。
JDBC提供了Statement、preparedStatement和CallableStatement三种方式来执行查询语句,其中Statement用于通用查询,preparedStatement用于执行参数化查询,而CallableStatement则是用于存储过程。
对于preparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,由于preparedStatement对象已于编译过所以器质性速度要快于Statement对象。
preparedStatement可以阻止常见的SQL注入攻击。
preparedStatement中,“?”叫做占位符,一个占位符只可以对应一个值。
Statement继承自Wrapper、preparedStatement继承自Statement、CallableStatement继承自PreparedStatement。
Statement:普通的不带参的查询SQL;支持批量更新,批量删除;
preparedStatement:可变参数的SQL,编译一次,执行多次,效率高;安全性好,有效防止SQL注入等问题,支持批量更新,批量删除;
CallableStatement:支持带参数的SQL操作,支持调用存储过程,提供了对输出和输入参数的支持;
Statement每次执行sql语句,数据库都要执行sql语句的编译 , 最好用于仅执行一次查询并返回结果的情形,效率高PreparedStatement。
PreparedStatement是预编译的,使用PreparedStatement有几个好处 :
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
2. 安全性好,有效防止Sql注入等问题。
3. 对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;
4. 代码的可读性和可维护性。
JDBC可以做什么
连接数据库
发送SQL语句到数据库
处理结果集
六个步骤
1、注册驱动
2、建立连接
3、创建statement对象
4、执行SQL语句
5、处理结果集
6、关闭相应资源
四要素
1、String driver = "jar包Driver类全包名"(使用的是oracle)
String dirver = "oracle.jdbc.driver.OracleDriver";
2、URL 确定连接到那个具体的数据库
jdbc:oracle:thin:@<SID> thin连接方式
String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
3、用户名
String user = "用户名";
4、密码
String password = "密码";
注册方式
1、使用类加载器
String driverName = "oracle.jdbc.driver.OracleDriver";
Class.forName(driverName);
2、实例化驱动对象
Driver driver = new oracle.jdbc.driver.OracleDriver();
注册驱动
DriverManager.registerDriver(driver);
3、使用property
System.setProperty("jdbc.drivers", "oracle.jdbc.driver.OracleDriver");
使用【系统配置】进行驱动注册,其中【第一个参数值固定】,第二个参数为驱动类的全包名。
补充: 也可以运行虚拟机时,设置运行参数。
这种方式也是通过系统配置进行驱动注册。
-Djdbc.drivers=oracle.jdbc.driver.OracleDriver
连接方式
1、利用Driver类直接连接(其实第一种底层也是通过Driver建立的连接)。
2、利用DriverManager.getConnection(url, user, passwd);(常用)
创建statement对象
Statement stmt = conn.createStatement();
String sql =”select * from s_emp”;
stmt.execute(sql);
stmt.executeQuery(sql);
stmt.executeUpdate(sql);
execute 返回boolean 执行返回结果集则true 否则false
executeQuery 返回结果集ResultSet
executeUpdate 返回int 执行影响了多少条数据
java.util.Date是java.sql.Date的父类
Java.util.Date utilDate=new java.util.Date();
Java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime());
事务提交
设置事务自动提交关闭 默认是开启的
conn.setAutoCommit(false);
conn.commit();手动提交事务
conn.rollback();回滚事务
注意: 【conn.close();事务会自动提交】。
同构
String sql = "insert into student values(?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setInt(1,7);
ps.setString(2, "王五");
ps.setInt(3, 21);
java.util.Date utilDate = new java.util.Date();
ps.setDate(4, new java.sql.Date(utilDate.getTime()));
ps.execute();
使用PrepareStatement的好处,除了效率高,还有就是 【省去了字符串的拼接】。
//添加到批处理
stmt.addBatch(sql);
//执行批处理
stmt.executeBatch();
获取当前时间System.currentTimeMillis();
java.util.Date start = System.currentTimeMillis();
java.util.Date end = System.currentTimeMillis();
syso("运行时间: "+(end-start));
DatabaseMetaData数据库元对象
MetaData元数据,描述数据的数据。
可以用来获得数据库的相关信息
获得数据库对象(表、视图、索引)的相关信息
获得数据库中列的信息
获得RusultSet中包含的列信息
获得数据库相关信息
metaData.getDatabaseProductName();
数据库名字
metaData.getDatabaseProductName();
数据库版本详细信息
metaData.getDatabaseProductName();
产品的主版本
metaData.getDatabaseProductName();
产品的次版本
获取数据库 里面 对象信息
ResultSet getTables(
String catalog, //null
String schema, //用户名
String tableName,
String types[]) throws SQLException;
获得数据库中表相关信息
catalog:
schema:
tableName: 表名
types: 具体类型,表、视图、索引、同义词
metaData.getTables(catalog,schema,tableName,types);
catalog,schema:在SQL标准下这两个都属于抽象概念,用来解决命名冲突问题。
从概念上说,一个数据库系统包含多个Catalog,每个Catalog包含多个Schema,而每个Schema又包含多个数据库对象(表、视图、索引)。
也可以说一个数据库对象必然属于一个schema,而schema又属于一个catalog。这样我们就可以得到该数据库对象的完全限定名称从而解决命名冲突的问题了
从实现的角度来看,各种数据库系统对Catalog和Schema的支持和实现方式千差万别,针对具体问题需要参考具体的产品说明书常用实现方式是使用【数据库名作为Catalog名】,使用【用户名作为Schema名】。
数据库 Catalog Schema
Oracle 不支持 用户名
MySql 不支持 数据库名
具体应用:
rs = metaData.getTables(null,"TEST",null,new String[]{"TABLE"});
while(rs.next()) {
String tName = rs.getString("TABLE_NAME");
String tType = rs.getString("TABLE_TYPE");
}
通过数据字典可以实现相同功能:
select table_name from user_tables;
查询出来的BIN$开头的属于数据库回收站里面的残留信息。
purge recyclebin; 可以【清空回收站】
获取数据库中列信息
metaData.getColumns(catalog,schema,tableName,columnName);
rs = metaData.getColumns(null,"TEST","STUDENT",null);
while(rs.next()){
String colName = rs.getString("COLUMN_NAME");
String colType = rs.getString("TYPE_NAME");
}
获取ResultSet中包含的列信息
包含多少列
每列都是什么数据类型
ResultSetMetaData metaData = rs.getMetaData();
//获取列数
int columnNum = metaData.getColumnCount();
for(int i = 1;i <= columnNum;i++){
//获取每一列名称
syso(metaData.getColumnName(i));
//获取每一列类型
syso(metaData.getColumnTypeName(i));
}