JDBC

使用java代码(程序)发送sql语句的技术,就是jdbc技术!

JDBC与数据库之间的通信是通过Socket完成的,因此我们可以把数据库当成一个SocketServer的提供方,因此当SocketServer返回数据的时候(类似于SQL结果集的返回)其流程是:服务端程序数据(数据库) -> 内核Socket Buffer -> 网络 -> 客户端Socket Buffer -> 客户端程序(JDBC所在的JVM内存)

 

数据库收到sql语句后执行步骤

  1. 检查语法是否正确
  2. 检查是否有足够的权限
  3. 把sql加入到sql缓冲区
  4. 数据库取出sql缓冲区的执行任务执行

使用jdbc发送sql前提

登录数据库服务器(连接数据库服务器)

数据库的IP地址,端口

数据库用户名,密码


JDBC接口核心的API:

java.sql.* 和 javax.sql.*

|- Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。

|- connect(url, properties):       连接数据库的方法。
    url: 连接数据库的URL
        url语法: jdbc协议:数据库子协议://主机:端口/数据库
    user: 数据库的用户名
    password: 数据库用户密码

|- DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序

|- registerDriver(driver) :      注册驱动类对象

|- Connection  getConnection(url,user,password);      获取连接对象

|- Connection接口:      表示java程序和数据库的连接对象

|- Statement  createStatement() :      创建Statement对象

|- PreparedStatement  prepareStatement(String sql)       创建PreparedStatement对象

|- CallableStatement  prepareCall(String sql)      创建CallableStatement对象

  |- void setAutoCommit(boolean autoCommit) ;      -设置事务是否自动提交。设置为false,表示手动提交事务。
  |- void commit();      -手动提交事务
  |- void rollback() ;      -回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)
  |- Savepoint setSavepoint(String name)     -在当前事务创建一个给定名称的保存点,并返回表示它的新Savepoint 对象

|- Statement接口:      用于执行静态的sql语句

|- boolean  execute(String sql) :      增删改查(true表示执行的是查询语句,false表示执行的是insert,delete,update等)

    |- ResultSet  getResultSet():        获取查询结果

|- int  executeUpdate(String sql) :      增删改(DDL,DML)返回影响行数

|- ResultSet  executeQuery(String sql) :    (DQL)

    |- void  addBatch(String sql):      -添加批处理
    |- void  clearBatch():      -清空批处理
    |- int[]  executeBatch():      -执行批处理

|-- PreparedStatement接口:     用于执行预编译sql语句

|- int  executeUpdate() :      执行预编译的更新sql语句(DDL,DML)
|-ResultSet  executeQuery() :      执行预编译的查询sql语句(DQL)
    |- void setXXX(int parameterIndex, value) :   将指定参数设置为给定值

|--- CallableStatement接口:     用于执行存储过程的sql语句(call xxx)

-ResultSet  executeQuery() :      调用存储过程的方法

|- ResultSet接口:     用于封装查询出来的数据

|- boolean  next() :      将光标移动到下一行     光标指向当前行数据,没有下一行时返回false

|- getXX() :      从当前行获取列的值     可以通过 索引编号(从1开始) 或列名称(不区分大小写) 获取值


JDBC连接到数据库的3种方式

public class Demo {
    //连接数据库的URL
    private String url = "jdbc:mysql://localhost:3306/day17";   //jdbc协议:数据库子协议:主机:端口/连接的数据库
    private String user = "root";   //用户名
    private String password = "123456";   //密码

1.用驱动程序连接
    public void test1() throws Exception{
                //1.创建驱动程序类对象
       	        //Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本   
               	Driver driver = new com.mysql.jdbc.Driver(); //新版本
 		    //设置用户名和密码 
		    Properties props = new Properties(); 
		    props.setProperty("user", user);
		    props.setProperty("password", password); 
		//2.连接数据库,返回连接对象conn 
		Connection conn = driver.connect(url, props); 
	}
2.用驱动管理器类连接数据库 
	public void test2() throws Exception{
		Driver mysql_driver = new com.mysql.jdbc.Driver();
		Driver oracle_driver = new com.oracle.jdbc.Driver(); 
		//1.注册驱动程序(可以注册多个驱动程序) 
		DriverManager.registerDriver(mysql_driver);
		DriverManager.registerDriver(oracle_driver);
		//2.连接到具体的数据库,获取连接对象conn
		Connection conn = DriverManager.getConnection(url, user, password); 
	}

--3.加载驱动程序类来注册驱动程序 (推荐使用)
	public void test3() throws Exception{
		//1.通过得到字节码对象的方式加载静态代码块,加载驱动程序
		Class.forName("com.mysql.jdbc.Driver"); 
		//2.连接到具体的数据库,获取连接对象conn
		Connection conn = DriverManager.getConnection(url, user, password); 
	}
}

 


使用Statement执行sql语句


   1.执行DDL语句:

数据定义语言(create / drop / alter)

//执行DDL语句(创建表)
public void test1(){
	Statement stmt = null;
	Connection conn = null;
	try {
		//1.加载驱动程序
		Class.forName("com.mysql.jdbc.Driver");
		//2.获取连接对象conn
		conn = DriverManager.getConnection(url, user, password);
		//3.创建Statement对象stmt
		stmt = conn.createStatement();
		//4.准备sql语句
		String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))";
		//5.发送sql语句,执行sql语句,得到返回结果
		int count = stmt.executeUpdate(sql);
		//6.输出
		System.out.println("影响了"+count+"行!");
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException(e);
	} finally{
		//7.关闭连接(顺序:后打开的先关闭)
		if(stmt!=null)
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		if(conn!=null)
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
	}
}

   2.执行DML语句:

数据操作语句(insert / delete /update / truncate)

JdbcUtil:创建一个工具类,将数据库的注册驱动程序,获取连接对象,释放资源等公共步骤 都包装JdbcUtil工具类中,使用时直接调用

增加
public void testInsert(){
	Connection conn = null;
	Statement stmt = null;
	try {	
		//1.通过工具类获取连接对象
		conn = JdbcUtil.getConnection();
		//2.创建Statement对象
		stmt = conn.createStatement();
		//3.sql语句
		String sql = "INSERT INTO student(NAME,gender) VALUES('李四','女')";
		//4.执行sql
		int count = stmt.executeUpdate(sql);
		System.out.println("影响了"+count+"行");
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException(e);
	} finally{
		//关闭资源
		JdbcUtil.close(conn, stmt);
	}
}

修改
public void testUpdate(){
	Connection conn = null;
	Statement stmt = null;
	//模拟用户输入
	String name = "陈六";
	int id = 3;
	try {
		conn = JdbcUtil.getConnection();			
		stmt = conn.createStatement();			
		String sql = "UPDATE student SET NAME='"+name+"' WHERE id="+id+"";			
		int count = stmt.executeUpdate(sql);
		System.out.println("影响了"+count+"行");			
	} catch (Exception e) {···} finally{···}
}

删除
public void testDelete(){
	Connection conn = null;
	Statement stmt = null;
	//模拟用户输入
	int id = 3;
	try {
		conn = JdbcUtil.getConnection();			
		stmt = conn.createStatement();			
		String sql = "DELETE FROM student WHERE id="+id+"";			
		int count = stmt.executeUpdate(sql);			
		System.out.println("影响了"+count+"行");			
	} catch (Exception e) {···} finally{···}
}

 


   3.执行DQL语句:

数据查询语言(select / show)

public void test(){
	Connection conn = null;
	Statement stmt = null;
	try{
		conn = JdbcUtil.getConnection();
		stmt = conn.createStatement();
		String sql = "SELECT * FROM student";
		//执行sql,返回结果ResultSet对象
		ResultSet rs = stmt.executeQuery(sql);			
	 //*移动光标,遍历结果
		while(rs.next()){
	          //1.根据索引 取出列值
			int id = rs.getInt(1);
			String name = rs.getString(2);
			String gender = rs.getString(3);	
	          //2.根据列名称 取出列值
			int id = rs.getInt("id");
			String name = rs.getString("name");
			String gender = rs.getString("gender");
			System.out.println(id+","+name+","+gender);
	}}catch(Exception e){···}finally{···}
}

 


使用预编译PreparedStatement执行sql语句

 ? 表示一个参数的占位符

增加
public void testInsert() {
	Connection conn = null;
	PreparedStatement pstmt = null;
	try {
		//1.获取连接
		    conn = JdbcUtil.getConnection();			
	    //*2.准备预编译的sql
		    String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)"; //?表示一个参数的占位符			
	    //*3.执行预编译sql语句(只检查语法,不执行)         --- sql语句放入缓冲区,没有参数
		    pstmt = conn.prepareStatement(sql);	
	    //*4.设置参数值
	        /**
		 * 参数一: 参数位置,从1开始
		 * 参数二: 具体数据
		 */
	        pstmt.setString(1, "李四");
	        pstmt.setString(2, "男"); 
	    //*5.发送参数,执行sql          --- 参数传入缓冲区并执行
	        int count = pstmt.executeUpdate();
	        System.out.println("影响了"+count+"行");
	} catch (Exception e) {
	        e.printStackTrace();
	        throw new RuntimeException(e);
	} finally {
	        JdbcUtil.close(conn, pstmt);
	}
}
修改
	        ······
	    //2.准备预编译的sql
	        String sql = "UPDATE student SET NAME=? WHERE id=?";   //?表示一个参数的占位符
	    //3.执行预编译sql语句(检查语法)
	        pstmt = conn.prepareStatement(sql);
	    //4.设置参数值
	        pstmt.setString(1, "王五");
	        pstmt.setInt(2, 9);
	    //5.发送参数,执行sql
	        int count = pstmt.executeUpdate();
	        System.out.println("影响了"+count+"行");
	        ······
删除
	        ······
	    //2.准备预编译的sql
	        String sql = "DELETE FROM student WHERE id=?"; //?表示一个参数的占位符
	    //3.执行预编译sql语句(检查语法)
	        pstmt = conn.prepareStatement(sql);
	    //4.设置参数值
	        pstmt.setInt(1, 9);
	    //5.发送参数,执行sql
	        int count = pstmt.executeUpdate();
	        System.out.println("影响了"+count+"行");
	        ······
查询
	        ······
	    //1.获取连接
	        conn = JdbcUtil.getConnection();
	    //2.准备预编译的sql
	        String sql = "SELECT * FROM student"; 
	    //3.预编译
	        pstmt = conn.prepareStatement(sql);
	    //4.执行sql
	        rs = pstmt.executeQuery();
	    //5.遍历rs
	        while(rs.next()){
	            int id = rs.getInt("id");
	            String name = rs.getString("name");
	            String gender = rs.getString("gender");
	            System.out.println(id+","+name+","+gender);}
	    //关闭 rs,pstmt,conn ······

 

PreparedStatement 对比 Statment

  1. 语法不同:PreparedStatement可以使用预编译的sql,而Statment只能使用静态的sql
  2. 效率不同: PreparedStatement可以使用sql缓存区,效率比Statment高
  3. 安全性不同: PreparedStatement可以有效防止sql注入,而Statment不能防止sql注入。

推荐使用PreparedStatement


使用CallableStatement执行存储过程

sql存储过程:

DELIMITER $
CREATE PROCEDURE pro_findById(IN sid INT,OUT sname VARCHAR(20) )
BEGIN
	SELECT Name INTO sname FROM student WHERE id=sid;
END $

执行带有输入输出参数的存储过程:

    注意: 所有调用存储过程的sql语句都是使用executeQuery方法执行!

public void test(){
	Connection conn = null;
	CallableStatement cstmt = null;
	ResultSet rs = null;
	try {
		//获取连接
		conn = JdbcUtil.getConnection();
		//准备sql
		String sql = "CALL pro_findById(?,?)"; //第一个?是输入参数,第二个?是输出参数			
		//预编译
		cstmt = conn.prepareCall(sql);			
	//*设置输入参数
		cstmt.setInt(1, 6);
	//*设置输出参数(注册输出参数)
		/**
		 * 参数一: 参数位置
		 * 参数二: 存储过程中的输出参数的jdbc类型  VARCHAR(20)
		 */
		cstmt.registerOutParameter(2, java.sql.Types.VARCHAR);		
	//*发送参数,执行       //注意: 所有调用存储过程的sql语句都是使用executeQuery方法执行!
		cstmt.executeQuery();   //结果不是返回到ResultSet结果集中,而是返回到输出参数中			
	//*得到输出参数的值
		/**
		 * 索引值: 预编译sql中的输出参数的位置
		 */
		String result = cstmt.getString(2);   //CallableStatement的getXX方法专门用于获取存储过程中的输出参数			
		System.out.println(result);
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException(e);
	} finally {
		JdbcUtil.close(conn, cstmt ,rs);
	}
}

-批处理

批量保存信息,批量执行sql语句

//获取连接 -> 准备sql -> 创建stmt ->
//添加批处理
    stmt.addBatch(sql1);   //Statement添加需要传入sql语句,
    stmt.addBatch(sql2);
    stmt.addBatch(sql3);

    pstmt.setXXX(1,value1);//PreparedStatement要先设置参数
    pstmt.setXXX(2,value2);
    pstmt.setXXX(3,value3);
    pstmt.addBatch();   //PreparedStatement添加不需要传入SQL
//批量执行 
    stmt.executeBatch();
//清空批处理
    stmt.clearBatch();
     //关闭连接

-获取插入数据的自增长值

//1.创建PreparedStatement对象时,在参数中指定返回自增长标记
    pstmt = conn.prepareStatement(sql_dept, Statement.RETURN_GENERATED_KEYS);
    ······
//2.执行sql语句更新后,获取自增长列
    rs = pstmt.getGeneratedKeys();
        if (rs.next()) {
        autoId = rs.getInt(1);
    }

事物

基本概念:
事务是指一组最小逻辑操作单元,里面有多个操作组成。 组成事务的每一部分必须要同时提交成功,如果有一个操作失败,整个操作就回滚。

事务ACID特性:
    原子性(Atomicity)   是一个最小逻辑操作单元
                事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
    一致性(Consistency)   事务过程中,数据处于一致状态
                事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
    隔离性(Isolation)   事务与事务之间是隔离的
                事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
    持久性(Durability)   事务一旦提交成功,对数据的更改会反映到数据库中
                持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
API:

  |- void setAutoCommit(boolean autoCommit) ;    -设置事务是否自动提交。默认添加并为为true。设置为false,表示手动提交事务。
  |- void commit();    -手动提交事务
  |- void rollback() ;    -回滚(出现异常时候,所有已经执行成功的代码需要回退到事务开始前的状态。)
  |- Savepoint setSavepoint(String name)    -在当前事务创建一个给定名称的保存点,并返回表示它的新Savepoint 对象

 

// 例:转账,使用事务,回滚到指定的代码段
public void trans() {
	//*定义个标记
	Savepoint sp = null;
	
	// 第一次转账
	String sql_zs1 = "UPDATE account SET money=money-1000 WHERE accountName='张三';";
	String sql_ls1 = "UPDATE account SET money=money+1000 WHERE accountName='李四';";
	// 第二次转账
	String sql_zs2 = "UPDATE account SET money=money-500 WHERE accountName='张三';";
	String sql_ls2 = "UPDATE1 account SET money=money+500 WHERE accountName='李四';";
	try {
		conn = JdbcUtil.getConnection(); // 默认开启的隐式事务自动提交
		conn.setAutoCommit(false);       // 主动设置为事务手动提交
		/*** 第一次转账 ***/
		pstmt = conn.prepareStatement(sql_zs1);
		pstmt.executeUpdate();
		pstmt = conn.prepareStatement(sql_ls1);
		pstmt.executeUpdate();
			
	//*保存点,回滚到sp这个位置
		sp = conn.setSavepoint(); 
		
		/*** 第二次转账 ***/
		pstmt = conn.prepareStatement(sql_zs2);
		pstmt.executeUpdate();
		pstmt = conn.prepareStatement(sql_ls2);
		pstmt.executeUpdate();
	
	} catch (Exception e) {//出现异常,回滚事物
		try {
			conn.rollback(sp);   // 回滚 Savepoint对象之后进行的更改
			conn.rollback();   // 回滚 当前事务中进行的所有更改
		} catch (SQLException e1) {
		}
		e.printStackTrace();
	} finally {
		try {
			// 提交
			conn.commit();
		} catch (SQLException e) {
		}
		JdbcUtil.closeAll(conn, pstmt, null);
	}
}

Jdbc中大文本类型的处理

Oracle中大文本数据类型,

Clob    长文本类型 (MySQL中不支持,使用的是text)
Blob    二进制类型

MySQL数据库,

Text    长文本类型
Blob    二进制类型
-- 例:大数据类型
CREATE TABLE test(
     id INT PRIMARY KEY AUTO_INCREMENT,
     content LONGTEXT,
     img LONGBLOB
);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值