JDBC


访问数据库的技术叫JDBC,对数据库的数据进行添加,删除,修改和查询
JDBC的API,存放在java.sql包中
java.sql.Connection:负责连接数据库
java.sql.Statement:负责执行数据库sql语句
java.sql.ResultSet:负责存放查询结果

JDBC

JDBC是一套面向对象的应用程序接口,指定了统一的访问各种关系型数据库的标准接口。JDBC是一种底层的API,因此访问数据库时需要嵌入SQL语句。
JDBC主要完成以下几个任务
1.与数据库建立连接
2.向数据库发送SQL语句
3.处理从数据库返回的结果

JDBC的总体结构由4个组件构成:应用程序,驱动程序管理器,驱动程序和数据源

JDBC驱动程序类型

JDBC并不能直接访问数据库,必须依赖于数据库厂商提供的JDBC驱动程序。
JDBC驱动基本分为以下几种
1.JDBC-ODBC桥:依靠ODBC驱动器和数据库通信。这种连接方式必须将ODBC二进制代码加载到使用该驱动程序的每台客户机上。
2.本地API一部分用java编写的驱动程序:这类驱动程序把客户机的API上的JDBC调用转换为Oracle,DB2,Sybase或其他DBMS的调用。这种驱动程序也需要将某些二进制代码加载到每台客户机上,
3.JDBC网络驱动:这种驱动程序将JDBC转换为与DBMS无关的网络协议,又被某个服务器转换为一种DBMS协议,是一种利用java编写的JDBC驱动程序,也是最为灵活的JDBC驱动程序。这种方案的提供者提供了适合于企业内部互联网用的产品。为使这种产品支持Internet访问,需要处理Web提出的安全性,通过防火墙的访问等额外的要求。
4.本地协议驱动:这是一种纯java的驱动程序。这种驱动程序将JDBC调用直接转换为DBMS所使用的网络协议,允许从客户机上直接调用DBMS服务器
JDBC网络驱动和本地协议驱动是JDBC访问数据库的首选,这两类驱动程序提供了java的所有优点。

各种数据库产品不同,厂商也不同,连接的方式也不同。JDBC机制提供了“驱动程序"的概念。对于不同的数据库,程序只需要使用不同的驱动。这种连接数据库的一种方式:数据库厂商驱动
在微软公司的Windows中,预先设计了一个ODBC(开放数据库互连)功能,由于ODBC是微软公司的产品,所以它几乎可以连接到所有在Windows平台下运行的数据库,由它连接到特定的数据库,不需要具体的驱动。而JDBC就只需要连接到ODBC就可以了。通过ODBC就可以连接到ODBC支持的任意一种数据库,这种连接方式称为JDBC-ODBC桥。这种方法让java连接到数据库的驱动程序称为JDBC-ODBC桥接驱动器。

JDBC-ODBC桥

JDBC-ODBC桥是一个JDBC驱动程序,完成从JDBC到ODBC操作之间的转换工作。
JDBC桥作为连接数据库的过渡技术,现在已经不被广泛应用了。但不代表其已经被淘汰。java可以利用JDBC-ODBC桥访问几乎所有的数据库。
使用JDBC-ODBC桥连接数据库的步骤如下
1.加载JDBC-ODBC桥的驱动程序

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

通过Class类的静态方法forName()可加载sun,jdbc,odbc包中的JdbcOdbcDriver类来建立JDBC-ODBC桥
2.使用Connection接口,并通过DriverManager类的静态方法getConnection()创建连接对象

Connection conn= DriverManager.getConnection(”jdbc:odbc:数据源名字“,"user name","password");

3.向数据库发送SQL语句
使用Statement接口声明一个SQL语句对象,并通过刚才创建的连接数据库对象conn的createStatement()方法创建这个SQL对象

Statement sql=conn.createStatement();

JDBC中常用的类和接口

(1)Connection接口

Connection接口代表与特定的数据库的连接
常用方法

方法说明
createStatement()创建Staement对象
createStatement(int resultSetType,int resultSetConcurrency)创建一个Statement对象,该对象将生成具有给定类型,并发性和可保存性的ResultSet对象
preparedStatement(String sql)创建一个 PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
isReadOnly()检索此 Connection对象是否处于只读模式。
setReadOnly(boolean readOnly)将此连接设置为只读模式,默认是非只读模式。
commit()使自上次提交/回滚以来所做的所有更改都将永久性,并释放此 Connection对象当前持有的任何数据库锁。
rollback()撤消在当前事务中所做的所有更改,并释放此 Connection对象当前持有的任何数据库锁。
close()立即释放此 Connection对象的数据库和JDBC资源,而不是等待它们被自动释放

(2)Statement接口

statement是java中的一个连接数据库的一个重要接口,在建立与数据库的连接之后,向数据库发送执行的sql语句(执行不带参数的简单sql)

JDBC中有三种Statement 接口
1.Statement :执行不带参数的简单sql
2.PreparedStatement (PreparedStatement 继承Statment) :执行动态的sql语句
3.CallableStatement (CallableStatement继承PreparedStatement ) :执行对数据库的存储过程的调用

Statement的常用方法

方法说明
excute(String sql)执行静态的select语句,语句可能返回多个结果集
executeQuery(String sql)执行给定的select语句,语句返回单个Resultset对象
excutebatch()将一批命令交给数据库执行,如果全部命令执行成功,则返回更新计数组成的数组。数组元素的顺序与添加sql语句的顺序对应
addBatch(String sql)将给定的sql命令添加到此Statement对象的当前命令列表中。如果程序不支持批量处理,将抛出异常
executeUpdate()用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
close()释放Statement实例占用的数据库和JDBC资源

少量语句Statement可能会发生SQL注入危险,所以一般不使用
大量语句使用Statement的addBatch

(3)PreparedStatement接口

PreparedStatement接口用来动态的执行SQL语句。通过PreparedStatement实例执行的动态SQL语句,将被预编译并保存到PreparedStatement实例中,从而可以反复地执行该SQL语句
PreparedStatement接口的常用方法

方法说明
.executeQuery()在此PreparedStatement对象中执行SQL查询,并返回该查询生成的ResultSet对象
.excuteUpate()执行前面包含参数的动态INSERT,UPDATE或DELETE语句,返回一个整型
setXXX(int dex,object o)XXX为设置参数的类型,object的类型对应XXX的类型(int,FLoat,Long,Double,Boolean,Date,String) 将指定位置的参数设置为XXX值
clearParameters()清除当前所有参数的值

预处理语句
通过Connection对象的PreparedStatement(String sql)方法对SQL语句进行预处理,生成数据库底层的内部命令,并将该命令封装在PreparedStatement对象中。通过调用相应方法,执行底层数据库命令。
预处理可以使用通配符“ ”来代替任何字段值

PreparedStatement sql=con.preparedStatement("select *from tb_stu where id="?");

然后通过setXXX来设置通配符所表示的值

sql.setint(1,2);
//1表示从左到右的第一个通配符,2表示设置的通配符的值

注:setXXX使用参数匹配的方法,还可以setObject()方法为各种类型的参数赋值 如:sql.setObject(2,1);

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","root","123456");
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            PreparedStatement sql=conn.prepareStatement("select * from tb_student where id= ?");  //预处理语句
            sql.setInt(1,19);
            ResultSet res=sql.executeQuery();
            while(res.next()){
                String id=res.getString("id");
                String name=res.getString("name");
                String sex=res.getString("sex");
                System.out.println("学号:"+id+"姓名:"+name+"性别:"+sex);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

(4)CallableStatement 接口

除了PreparedStatement外,还提供了CallableStatement 来调用存储过程。CallableStatement 是PreparedStatement的子接口
可以通过Connection的prepareCall()方法创建CallableStatement 对象,使用CallableStatement 对象可以同时处理IN参数和OUT参数
常用方法

方法说明
setXXX()设置IN参数
registerOutParameter(int parameterIndex, SQLType sqlType)将序号parameterIndex中的OUT参数 parameterIndex到JDBC类型 sqlType
getXXX()获取参数值

如何调用这个存储过程
CallableStatement对象通过setXXX()方法传入IN参数,如果已定义的存储过程返回OUT参数,则在执行CallableStatement对象以前必须先注册每个OUT参数的JDBC类型,注册JDBC类型通过registerOutParameter()方法实现。语句执行完后,CallableStatement的getXXX()方法获取参数值。XXX表示各参数所注册的JDBC类型所对应的java类型

如一个例子,根据学生学号,查询其姓名

CRATE PROCEDURE prc_getStuname(@stuno VARCHAR(16),@stuname VARCHAR(16) OUTPUT)
AS
BEGIN
SELECT @stuname=STUNAME FROM T_STUDENT WHERE STUNO=@stuno
END
import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        try {
            conn = DriverManager.getConnection("jdbc:odbc:Dsschool");   //与数据源建立连接
            CallableStatement cs=conn.prepareCall("{call prc_getStuname(?,?)}");
            cs.setString(1,"0001");     //设置IN参数
            cs.registerOutParameter(2, Types.CHAR);    //注册OUT参数
            cs.executeQuery();    //执行存储过程
            String result=cs.getString(2);    //获取参数值
            cs.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Statement 接口提供了执行语句和获取结果的基本方法。PreparedStatement 接口添加了处理 IN 参数的方法;而 CallableStatement 添加了处理 OUT 参数的方法。

(5)DriverManager类

DriverManager类用来管理数据库中的所有驱动程序。它是JDBC的管理层,作用于用户和驱动程序之间,跟踪可用的驱动程序,并在数据库的驱动程序之间建立连接,如果通过getConnection()方法可以建立连接,则经连接返回,否则抛出SQLException
异常。zhid
常用方法

方法说明
getConnection(String url,String user,String password)指定3个入口参数(连接数据库的URL,用户名,密码)来获取与数据库的连接
setLoginTimeout()获取驱动程序试图登录到某一数据库时可以等待的最长时间,以秒为单位
println(String message)将一条消息打印到当前JDBC日志流中

(6)ResultSet接口

ResuleSet接口类似一个临时表,用来暂时存放数据库查询操作所获得的结果集。并且ResultSet还提供当前数据行的指针,指针刚开始指向第一行,通过next()方法移向下一行
ResultSet接口常用方法

方法说明
getXXX()以xxx形式获取此ResultSet对象的当前行的指定列值。如果列值是NULL,则返回0
first()将指针移到当前记录的第一行
last()将指针移到当前记录的最后一行
next()将指针向下移一行
absolute(int index)将指针移到ResultSet给定编号的行
updateXXX()用xxx值更新指定列
getrow()查看当前行的索引号
insertRow()将插入行的内容插入到数据库
updateRow()将当前行的内容同步到数据库
deleteRow()删除当前行,但并不同步到数据库中,而是在执行close()方法同步到数据库

用updateXXX()更新指定列。但该方法没有对数据同步到数据库中,需要执行updateRow()或insertRow()方法更新数据库

数据库操作

(1)连接数据库

访问数据库,首先要加载数据库的驱动程序(只需要在第一次访问数据库时加载一次),然后每次访问数据时创建一个Connection对象,接着执行操作数据库的SQL语句,最后在完成数据库操作后销毁前面创建的Connection对象,释放与数据库的连接

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");     //8.0版本  使用com.mysql.cj.jdbc.Driver   老版本使用com.mysql.jdbc.Driver
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");   
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
如果连接出现这种情况
conn = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/test”,“root”,“123456”); 就改成 con= DriverManager.getConnection(“jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC”,“root”,“123456”);
在后面加**?serverTimezone=UTC**

(2)向数据库发送SQL语句

要执行SQL语句首先要获得Statement类对象。通过Connection对象的createStatement()方法获取Statement对象

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");     //8.0版本  使用com.mysql.cj.jdbc.Driver   老版本使用com.mysql.jdbc.Driver
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");   
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            Statement sql=conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

(3)处理查询结果集

通过Statement对象的相应方法实现对数据库的查询和修改,并将查询的结果集存放在ResultSet类的对象中

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
       try {
            Class.forName("com.mysql.cj.jdbc.Driver");     //8.0版本  使用com.mysql.cj.jdbc.Driver   老版本使用com.mysql.jdbc.Driver
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");   
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            Statement sql=conn.createStatement();
            ResultSet res=sql.executeQuery("select * from tb_student");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

返回一个ResultSet对象,ResultSet对象一次只可以看到结果集中的一行数据,使用该类的next()方法可将光标从当前位置移向下一行

ResultSet类的next()方法的返回值是boolean类型,当游标移动到最后一行之后会返回false。

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");     //8.0版本  使用com.mysql.cj.jdbc.Driver   老版本使用com.mysql.jdbc.Driver
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");   
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            Statement sql=conn.createStatement();
            ResultSet res=sql.executeQuery("select * from tb_student");
            while(res.next()){
                String id=res.getString("id");
                String name=res.getString("name");
                String sex=res.getString("sex");
                System.out.println("学号:"+id+"姓名:"+name+"性别:"+sex);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

预处理语句PreparedStatement
存储过程CallableStatement
前面有

(4)添加,修改,删除记录


import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        PreparedStatement sql;
        ResultSet res;
       try {
            Class.forName("com.mysql.cj.jdbc.Driver");     //8.0版本  使用com.mysql.cj.jdbc.Driver   老版本使用com.mysql.jdbc.Driver
            System.out.println("数据库驱动加载成功");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");   
            System.out.println("数据库连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
             sql=conn.prepareStatement("select * from tb_student");
            System.out.println("------增添删改操作之前的数据------");
            res=sql.executeQuery();
            while(res.next()){
                String id=res.getString("id");
                String name=res.getString("name");
                String sex=res.getString("sex");
                System.out.println("学号:"+id+"姓名:"+name+"性别:"+sex);
            } 
            sql=conn.prepareStatement("insert into tb_student values (?,?,?)");   //插入
            sql.setString(1,"0005");
            sql.setString(2,"张三");
            sql.setString(3,"男");
            sql.executeUpdate();
            sql=conn.prepareStatement("uddate tb_studnet set name =? where id="+"0001");   //更新
            sql.setString(1,"小李");   
            sql.executeUpdate();
            sql=conn.prepareStatement("delete tb_studnet where id="+"0002");    //删除
            sql.executeUpdate();
            System.out.println("------增添删改操作之后的数据------");
            sql=conn.prepareStatement("select * from tb_student");
            res=sql.executeQuery();
            while(res.next()){
                String id=res.getString("id");
                String name=res.getString("name");
                String sex=res.getString("sex");
                System.out.println("学号:"+id+"姓名:"+name+"性别:"+sex);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

(4)批处理Batch

当需要处理大量的SQL语句时,就需要Batch。尽量使用Statement,因为prepareStatement预编译空间有限,当数据量特别大时会发生异常。
另外批处理时需要将事务自动提交改为false

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        Statement st;
        ResultSet res;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("数据库驱动加载成功");

            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC","root","123456");
            System.out.println("数据库连接成功");

            conn.setAutoCommit(false);    //设为手动提交
            st=conn.createStatement();
            for(int i=0;i<20000;i++){
                st.addBatch("insert into  tb_student (stnuo,stuname) values("+i+",'gao')");
            }
            st.executeBatch();
            conn.commit();   //提交
        } catch (SQLException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

(5)时间段查询

java.sql.Date:表示年月日
java.sql.Time:表示时分秒
java.sql.Timestamp:表示年月日时分秒
构造方法需要传入long类型参数

import java.sql.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class Test {
    public static long getTime(String datestr){       //datestr格式:yyyy-MM-dd hh:mm:ss
        DateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        try {
            return format.parse(datestr).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            return 0;
        }
    } 
    public static void main(String[] args) {
        Connection conn= null;
        PreparedStatement sql;
        PreparedStatement sql2;
        ResultSet res;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("数据库驱动加载成功");

            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC","root","123456");
            System.out.println("数据库连接成功");
            
            sql=conn.prepareStatement("select  * from tb_user where regtime>? and regtime<?");         
            java.sql.Date start=new java.sql.Date (getTime("2019-10-01 21:23"));
            java.sql.Date end=new java.sql.Date (getTime("2019-10-07 21:23"));
            sql.setObject(1,start);
            sql.setObject(2,end);
            res=sql.executeQuery();
            while (res.next()){
                System.out.println(res.getInt("id")+" "+res.getString("username")+" "+res.getString("regtime"));   
            }
            
            
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

事务

(1).事务

事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位
事务开始于
·连接数据库操作,并执行一条DML语句(INSERT,UPDATE或DELETE)
·前一个事务结束后,又输入了另一条DML语句
事务结束于
·执行COMMIT或ROLLBACK语句
·执行一条DDL语句,这种情况下会自动执行COMMIT语句
·执行一条DCL语句,这种情况下会自动执行COMMIT语句
·断开数据库的连接
·执行一条DML语句,该语句失败了,这种情况下,会执行ROLLBACK语句

事务的ACID特性
1.原子性
事务时数据库的逻辑工作单位,事务中包括的操作要么都做,要么都不做
2.一致性
表示一个事务有一个事务操作失败时,所有更改的数据必须回到修改以前的状态
3.隔离性
一个事务的执行不能被其他事务干扰。即一个事务的内部操作及使用的数据对其他并发事务时隔离的,并发执行的各个事务之间不能相互干扰
4.持久性
一个事务一旦提交,它对数据库中数据的改变就是永久性的

事务隔离级别从低到高
·读取未提交 :也就是事务A在执行时,还未提交时,事务B可以看到
·读取已提交:事务A在执行时,在已提交后事务B才可以看到
·可重复读
·序列化:锁表

一般情况下都是读取已提交。

(2)事务操作

package Learn;

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        PreparedStatement sql;
        PreparedStatement sql2;
        ResultSet res;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("数据库驱动加载成功");

            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC","root","123456");
            System.out.println("数据库连接成功");

            conn.setAutoCommit(false);    //JDBC默认是true,自动提交  设为手动提交
            sql=conn.prepareStatement("insert  into tb_student(stuno,stuname) values(?,?)");         //事务开始
            sql.setString(1,"0001");
            sql.setString(2,"张三");
            sql.execute();

            sql2=conn.prepareStatement("insert  into tb_student(stuno,stuname) values(?,?)");         
            sql2.setString(1,"0001");
            sql2.setString(2,"张三");
            sql2.execute();


            conn.commit();   //提交                       事务结束
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
              try {
                conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

上述事务的操作会成功

import java.sql.*;

public class Test {
    public static void main(String[] args) {
        Connection conn= null;
        PreparedStatement sql;
        PreparedStatement sql2;
        ResultSet res;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            System.out.println("数据库驱动加载成功");

            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC","root","123456");
            System.out.println("数据库连接成功");

            conn.setAutoCommit(false);    //JDBC默认是true,自动提交  设为手动提交
            sql=conn.prepareStatement("insert  into tb_student(stuno,stuname) values(?,?)");         //事务开始
            sql.setString(1,"0001");
            sql.setString(2,"张三");
            sql.execute();

            sql2=conn.prepareStatement("insert  into tb_student(stuno,stuname) values(?,?,?)");        
            sql2.setString(1,"0001");
            sql2.setString(2,"张三");
            sql2.execute();


            conn.commit();   //提交                       事务结束
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

上述代码事务的第二个操作会执行失败,会出现异常,执行回滚操作ROLLBACK

CLOB(Character Large Object)

用于存储大量的文本数据,比如存本小说
大字段的操作常常是以流的方式来处理。

MySQl中相关类型

TINYTEXT最大长度为255(21–1)字符的TEXT列。
TEXT[(M)]最大长度为65,535(22–1)字符的TEXT列。
MEDIUMTEXT最大长度为16,777,215(23–1)字符的TEXT列。
LONGTEXT最大长度为4,294,967,295或4GB(24–1)字符的TEXT列。

向MySQL中插入CLOB数据
使用PreparedStatement的setClob(int index,Reader reader)方法 第一个参数是占位符的坐标,第二个参数是输入流


将info.txt文件的内容读入到SQL

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class CLOB {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement ps=null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            con= DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");
            
            
            ps=con.prepareStatement("insert  into user (name,info) values (?,?)");
            ps.setString(1,"张三");
            ps.setClob(2,new FileReader("d:/info.txt"));
            
            ps.executeUpdate();
            
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

得到CLOB


import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.*;

public class CLOB {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        Reader reader=null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            con= DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");


            ps=con.prepareStatement("insert  into user (name,info) values (?,?)");
            ps.setString(1,"张三");
            ps.setClob(2,new FileReader("d:/info.txt"));

            ps.executeUpdate();
            
            ps=con.prepareStatement("select * from user where id>?");          
            ps.setObject(1,1);
            
            rs=ps.executeQuery();         
            while(rs.next()){
                Clob clob=rs.getClob("info");       //读取CLOB
                reader=clob.getCharacterStream();
                int temp=0;
                while((temp=reader.read())!=-1){
                    System.out.println((char) temp);
                }
            }
            
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(rs!=null){
                try {
                    rs.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(ps!=null){
                try {
                    ps.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(con!=null){
                try {
                    con.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

BOLB

用于存储大量的二进制数据
也是用流来处理的
Mysql中相关类型:
TINYBLOB最大长度为255(25–1)字节的BLOB列。
BLOB[(M)]最大长度为65,535(26–1)字节的BLOB列。
MEDIUMBLOB最大长度为16,777,215(27–1)字节的BLOB列。
LONGBLOB最大长度为4,294,967,295或4GB(28–1)字节的BLOB列。


import java.io.*;
import java.sql.*;

public class BLOB {
    public static void main(String[] args) {
        Connection con=null;
        PreparedStatement ps=null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            con= DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC","root","123456");


            ps=con.prepareStatement("insert  into user (id,name,info) values (?,?,?)");
            ps.setInt(1,1);
            ps.setString(2,"张三");
            ps.setBlob(3, new FileInputStream("d:/test.jpg"));

            ps.executeUpdate();

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(ps!=null){
                try {
                    ps.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(con!=null){
                try {
                    con.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述
导入成功

在这里插入图片描述
右键点击查看Blob的值
在这里插入图片描述
导入成功

ORM

ORM(Object Relationship Mapping)的基本思想
表结构跟类对应
表中字段和类的属性对应
表中记录和对象对应

在这里插入图片描述
首先表中有如上数据

(1)表中的记录封装到Object数组中

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Demo1 {
    public static void main(String[] args) {
        Connection con= JDBCUntil.getConnection();
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            ps=con.prepareStatement("select name,salary,age from user where id =?");
            ps.setInt(1,1);

            rs=ps.executeQuery();
            
            while(rs.next()){
                Object[] objs= new Object[3];   //一个Object数组封装了一条记录的信息!
//				System.out.println(rs.getString(1)+"--"+rs.getDouble(2)+"--"+rs.getInt(3));
                objs[0]= rs.getObject(1);
                objs[1] = rs.getObject(2);
                objs[2] = rs.getObject(3);
                for(Object o:objs){
                    System.out.println(o);
                }
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
输出结果:
张三
20000.0
12

(2)将表中的记录封装到map中

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class Demo1 {
    public static void main(String[] args) {
        Connection con= JDBCUntil.getConnection();
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            ps=con.prepareStatement("select name,salary,age from user where id =?");
            ps.setInt(1,1);

            rs=ps.executeQuery();

            while(rs.next()){
                Map<Object,Object> row=new HashMap<>();      
                row.put("name",rs.getObject(1));
                row.put("salary", rs.getObject(2));
                row.put("age", rs.getObject(3));
                for(Object o:row.keySet()){
                    System.out.println(row.get(o));
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

(3)将表中将表中记录封装到javabean对象中

public class User {
    private int id;
    private String name;
    private int age;
    private Double salary;

    public User(int id, String name, int age, Double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public User() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }
}

import JDBCLearn.JDBCUntil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class Demo3 {
    public static void main(String[] args) {
        Connection con= JDBCUntil.getConnection();
        PreparedStatement ps=null;
        ResultSet rs=null;
        try {
            ps=con.prepareStatement("select * from user where id =?");
            ps.setInt(1,1);

            rs=ps.executeQuery();

            while(rs.next()){
               User user=null;   //一个Object数组封装了一条记录的信息!
               int id= (int) rs.getInt(1);
                String name=rs.getString(2);
                int age=rs.getInt(3);
                double salary=rs.getDouble(4);
                user=new User(id,name,age,salary);
                System.out.println(user.getName()+" "+user.getSalary());
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

  1. 8 ↩︎

  2. 16 ↩︎

  3. 24 ↩︎

  4. 32 ↩︎

  5. 8 ↩︎

  6. 16 ↩︎

  7. 24 ↩︎

  8. 32 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值