JDBC总结

JDBC总结

一、什么是JDBC

1、sun公司统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。其中JDBC驱动程序管理器是JDBC体系结构的核心。JDBC全称为:Java Data Base Connectivity。java数据库连接),它主要由接口组成。

2、组成JDBC的2个包:

(1) java.sql

(2) javax.sql

3、开发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的数据库实现(即数据库驱动)。

二、第一个JDBC程序

程序步骤:

1、搭建实验环境 :

(1)、在mysql中创建一个库,并创建user表和插入表的数据。

(2)、新建一个Java工程,并导入数据驱动。

2、载入驱动

Class.forName(“com.mysql.jdbc.Driver”);

3、建立连接

Connection con=new Connection;

String url=”jdbc:mysql://localhost:3306:/库名”;

String username=”roor”;

String password=”root”;

con=DriverManager.getConnection(“url”,”username”,”password”);

4、生成Statement对象,提交查询语句,返回结果集

Statement st=new Statement();

st=con.CreateStatement();

String sql=”Select id,name,birthday,email from myusers”;

5、遍历结果集

ResultSet rs=new ResultSet();

rs=st.executeQuery(sql)

While(rs.next()){

System.out.print(rs.getInt("id"));

System.out.print("\t"+rs.getString("name"));

System.out.print("\t"+rs.getDate("birthday"));

System.out.print("\t"+rs.getString("password"));System.out.println(rs.getString("email"));

}

6、释放资源(最好写在finally里面)

if(rs!=null){

try {

rs.close();

catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

if(st!=null){

try {

st.close();

catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

if(con!=null){

try {

con.close();

catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

三、程序详解

1、DriverManager

Jdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:

DriverManager.registerDriver(new Driver()),注意:在实际开发中,并不推荐采用这个方法注册驱动。查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。

推荐方式:Class.forName(“com.mysql.jdbc.Driver”);采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要import驱动的API,这样可使程序不依赖具体的驱动,使程序的灵活性更高。

DriverManager.getConnection(url, user, password),根据url获取数据库的链接。

2、数据库URL

 jdbc:mysql:[]//localhost:3306/test ?参数名:参数值

3、Connection

Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:

createStatement():创建向数据库发送sql的statement对象。

prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。

prepareCall(sql):创建执行存储过程的callableStatement对象。 

setAutoCommit(boolean autoCommit):设置事务是否自动提交。 

commit() :在链接上提交事务。

rollback() :在此链接上回滚事务。

4、Statement

Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:

execute(String sql):用于向数据库发送任意sql语句

executeQuery(String sql) :只能向数据发送查询语句。

executeUpdate(String sql):只能向数据库发送insert、update或delete语句

addBatch(String sql) :把多条sql语句放到一个批处理中。

executeBatch():向数据库发送一批sql语句执行。 

5、ResultSet

Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。

ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:

获取任意类型的数据

getObject(int index)

getObject(string columnName)

获取指定类型的数据,例如:

getString(int index)

getString(String columnName)

提问:数据库中列的类型是varchar,获取该列的数据调用什么方法?Int类型呢?bigInt类型呢?Boolean类型?

ResultSet还提供了对结果集进行滚动的方法:

next():移动到下一行

Previous():移动到前一行

absolute(int row):移动到指定行

beforeFirst():移动resultSet的最前面。

afterLast() :移动到resultSet的最后面。

6、释放资源

Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。

特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。

为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

四、使用JDBC处理大数据

在实际开发中,程序需要把大文本或二进制数据保存到数据库。

1、基本概念:大数据也称之为LOB(Large Objects),LOB又分为:clob:用于储存文本(Text)和blob:用于存储二进制数据,例如图像、声音、二进制文等。

2、对Mysql而言只有blob,而没有clob,mysql存储大文本采用的是Text,Text和blob分别又分为:

TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT

TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB 

3、(1)对于MySQL中的Text类型,可调用如下方法设置:

PreparedStatement.setCharacterStream(index,reader, length);

//注意length长度须设置,并且设置为int型

(2)对MySQL中的Text类型,可调用如下方法获取:

reader = resultSet. getCharacterStream(i);

reader = resultSet.getClob(i).getCharacterStream();

string s = resultSet.getString(i);

(3)对于MySQL中的BLOB类型,可调用如下方法设置:

PreparedStatement.setBinaryStream(i,inputStream, length);

(4)对MySQL中的BLOB类型,可调用如下方法获取:

nputStream in  = resultSet.getBinaryStream(i);

InputStream in  = resultSet.getBlob(i).getBinaryStream(); 

五、使用JDBC进行批处理

当需要向数据库发送一批sql语句执行时,应避免向数据库一条条的发送执行,而采用JDBC的批处理机制,以提升执行效率

1、实现批处理有两种方式,第一种方式:

Statement.addBatch(sql) list

执行批处理SQL语句

executeBatch()方法:执行批处理命令

clearBatch()方法:清楚批处理命令

Connection con= null;

Statement st = null;

ResultSet rs = null;

try {

conn = DBManagerDemo.getConnection();

String sql1 = "insert into myusers(name,password) 

values('kkk','123')";

String sql2 = "update myusers set password='123456' where id=3";

st = conn.createStatement();

st.addBatch(sql1);  //把SQL语句加入到批命令中

st.addBatch(sql2);  //把SQL语句加入到批命令中

st.executeBatch();

} finally{

DBManagerDemo.free(conn, st, rs);

}

2、第二种方式:

PreparedStatement.addBatch();

conn = DBManagerDemo.getConnection();

String sql = "insert into myusers(name,password) values(?,?)";

st = conn.prepareStatement(sql);

for(int i=0;i<50000;i++){

st.setString(1, "aaa" + i);

st.setString(2, "123" + i);

st.addBatch();

if(i%1000==0){

st.executeBatch();

st.clearBatch();

}

}

st.executeBatch();

六:获取数据库自动生成的主键

Connection con = DBManagerDemo.getConnection();

String sql = "insert into myusers(name,password) 

values('abc','123')";

PreparedStatement st = con.

prepareStatement(sql,Statement.RETURN_GENERATED_KEYS );

st.executeUpdate();

ResultSet rs = st.getGeneratedKeys();  //得到插入行的主键

if(rs.next())

System.out.println(rs.getObject(1));

七、使用JDBC调用存储过程

1、在mysql中编写存储过程

得到CallableStatement,并调用存储过程:

CallableStatement cs = con.prepareCall("{call 创建的存储过程名(?, ?)}");

设置参数,注册返回值,得到输出

cs.setString(1, "abcdefg");

cs.registerOutParameter(2, Types.VARCHAR);

cs.execute();

System.out.println(cs.getString(2));

八、事物

事物的概念:事物指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。

例如:A--B转账,对应于如下两条sql语句

Update from account set money=money+100 where name=’b’;

Update from account set money=money-100 where name=’a’;

步骤:

1、数据库开启事务命令

(1)、start transaction 开启事务

Connection.setAutoCommit(false);

(2)、Rollback 回滚事务

Connection.rollback();

(3)、Commit 提交事务

Connection.commit();

九、事务的特性(ACID)

1、(1)原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 

(2)、一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。

(3)、隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

(4)、持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

2、多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。

3、如果不考虑隔离性,可能会引发如下问题:

(1)、脏读:

指一个事务读取了另外一个事务未提交的数据。

这是非常危险的,假设A向B转帐100元,对应sql语句如下所示

1.update account set money=money+100 while name=‘b’;

2.update account set money=money-100 while name=‘a’;

当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。

(2)、不可重复读:

在一个事务内读取表中的某一行数据,多次读取结果不同。

例如银行想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户存了100元并提交了,银行接着又进行了一次查询,此时A帐户为300元了。银行两次查询不一致,可能就会很困惑,不知道哪次查询是准的。

和脏读的区别是,脏读是读取前一事务未提交的脏数据,不可重复读是重新读取了前一事务已提交的数据。

很多人认为这种情况就对了,无须困惑,当然是后面的为准。我们可以考虑这样一种情况,比如银行程序需要将查询结果分别输出到电脑屏幕和写到文件中,结果在一个事务中针对输出的目的地,进行的两次查询不一致,导致文件和屏幕中的结果不一致,银行工作人员就不知道以哪个为准了。

(3)、虚读(幻读)

是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

如丙存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后丙提交了,这时银行再统计发现帐户为600元了,造成虚读同样会使银行不知所措,到底以哪个为准。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值