一. JDBC的总结
1.jdbc---->访问数据库的一组接口,用来操作关系型数据库
简单来说就是一组规范,将所有关系型数据库都抽像出来的一组规 范。
2.作用:就是访问不同的数据库jdbc的语句是一样的,
3.访问数据库的4个步骤:
加载驱动:
Class.forName(“com.mysql.jdbc.Driver”)
注意:对于不同的版本驱动是不一样的
获得连接:
Connection conn=DriverManager.getConnetion(url,user,password)
这里的user和password对应的数据库的用户名和密码
创建声明:Statement st=conn.CreateStatement()
执行sql: st.execute(sql) 使用范围:任何语句
st.executeQuery(sql) 返回的是一个集合(ResultSet),对于Update不适用,对于遍历集合时用到next() 游标,注意游标第一次指向的是各属性的那一行
st.executeUptate(sql) 返回的是执行sql语句后所更新的条数(int)
4.JDBC中重要的两个类和接口:
DriverManager类:主要用来管理驱动和获得数据库的连接
Statement类:用来发送sql,包括三个方法: execute(),executeQuery(),executeUpdate()
Connection 接口:不能用来发送SQL,只是一个连接通道,用完要进行关闭
常用方法:
CreateStatement():创建声明
PreparedStatement():创建预编译的声明
setAutocommit(Boolean ):管理事务是否为自动提交,默认为True
Commit();提交
rollback():回退
ResultSet接口:
常用方法:next():移动光标
get(type):获得返回结果集中任何类型的数据
close():关闭资源,在1.7版本之后放在try(…sql)当执行完成自动关闭,无需在调用close()函数进行关闭
Jdbc的封装:
在这里插入代码片
package jdbcTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcUtil {
static String url="jdbc:mysql://localhost:3306/java1116";
static String userName="root";
static String password="tiger";
//封装jdbc,首先加载驱动,因为驱动只加载一次,所以放在静态块中
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
return DriverManager.getConnection(url, userName, password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
5.sql注入的含义:通过传递一个sql片段来破坏原有的sql语句,达到sql攻击的目的
6.为了实现动态参数引入和解决sql的注入PreparedStatement接口:
作用:
1.解决sql注问题
2.为不同的数据类型赋值更加方便
3.同一个sql执行时性能更好
如果sql语句中带有参数时用PreparedStatement
具体实例:
/**
* 购买图书
* @param userid
* @param bookid
* @return
*/
public static boolean buy(int userid,int bookid) {
//更新两表;库存表-1, 用户表: 余额-价格‘
String updata1="update bookstore set count=count-1 where bookid=?";
String updata2="update sys_user set remain=remain-(select price from book where bookid=?)where userid=?";
//查所剩于的数量和余额是否大于零
String query1="select count from bookstore where bookid=?";
String query2="select remain from sys_user where userid=?";
Connection conn=JdbcUtil.getConnection();
try(PreparedStatement ps_u1=conn.prepareStatement(updata1);
PreparedStatement ps_u2=conn.prepareStatement(updata2);
PreparedStatement ps_q1=conn.prepareStatement(query1);
PreparedStatement ps_q2=conn.prepareStatement(query2);
){
conn.setAutoCommit(false);
//完成了两个表的更新操作
ps_u1.setInt(1, bookid);
ps_u1.execute();
ps_u2.setInt(1, bookid);
ps_u2.setInt(2, userid);
ps_u2.execute();
//查询
ps_q1.setInt(1, bookid);
ResultSet rs1= ps_q1.executeQuery();
rs1.next();
int store=rs1.getInt(1);
ps_q2.setInt(1, userid);
ResultSet rs2=ps_q2.executeQuery();
rs2.next();
int remain=rs2.getInt(1);
if(store<0) {
throw new Exception("库存不足");
}else if(remain<0) {
throw new Exception("余额不足");
}else {
conn.commit();
}
System.out.println("购买成功 库存为"+store+"余额为"+remain);
return true;
}catch(Exception e) {
e.printStackTrace();
}finally {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}
7.JDBC中的Connection来解决事务的问题:
所谓的事务:就是用户自定义的最小单元,事务中的操作是一个整体,要么全做,要么全不做。
在事务中用到的方法:
1.setAutoCommit(boolean )
2.Commit()
3.rollback()
执行事务的框架:
Connection conn=JdbcUtil.getConnection();
try(){
//sql语句
conn.commit();
}catch (Exception e) {
rollback();
}finally {
//关闭资源
}
8.Jdbc对打大对象的读和取:
通过流的方式进行读和取
读方法:
setBinaryStream(1): 获得BLOb的输出流
CreateBlob() 创建一个大对象
取方法:
getBinaryStream(); 得到BLOb输入流
CreateBlob() 创建一个大对象
package jdbcTest;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class BigObject {
public static void main(String[] args) throws Exception {
//write();
read();
}
public static void write() throws Exception {
//将一张图片存到数据库中
//通过流的方式写入数据库中
String sql="insert into emp(empno,ename,picName,pic) values(null,?,?,?)";
//只有表的主键为自动增长时才能在插入数据的时候写null
try(Connection conn=JdbcUtil.getConnection();
PreparedStatement ps=conn.prepareStatement(sql);){
//创建一个Blob对象
Blob blob=conn.createBlob();
//获得输出流,利用os将从磁盘中得到的图片写入到数据库中
OutputStream os=blob.setBinaryStream(1);
FileInputStream fis=new FileInputStream("d:/111.jpg");
byte[] by=new byte[100];//缓存数组
int size=-1;
while((size=fis.read(by))!=-1) {
os.write(by, 0, size);
}
ps.setString(1,"莫清");
ps.setString(2, "宿舍");
ps.setBlob(3, blob);
ps.execute();
System.out.println("执行完毕");
fis.close();
os.close();
}
}
public static void read() throws Exception {
String sql="select * from emp where empno=1";
try(Connection conn=JdbcUtil.getConnection();
//如果没有?号的时候没有必要用PreparedStatement
Statement st=conn.createStatement();
//看是否返回结果集
ResultSet rs=st.executeQuery(sql)){
rs.next();
Blob blob=rs.getBlob(4);
InputStream is=blob.getBinaryStream();
FileOutputStream fos=new FileOutputStream("d:/picture/hh.jpg");
byte[] by=new byte[100];
int size=-1;
while((size=is.read(by))!=-1) {
fos.write(by, 0, size);
}
is.close();
fos.close();
}
}
}