JDBC

mac2022-07-05  25

文章目录

JDBCJDBC驱动程序类型JDBC-ODBC桥JDBC中常用的类和接口(1)Connection接口 (2)Statement接口(3)PreparedStatement接口(4)CallableStatement 接口(5)DriverManager类(6)ResultSet接口 数据库操作(1)连接数据库 (2)向数据库发送SQL语句(3)处理查询结果集(4)添加,修改,删除记录(4)批处理Batch(5)时间段查询 事务(1).事务 (2)事务操作 CLOB(Character Large Object)BOLBORM(1)表中的记录封装到Object数组中(2)将表中的记录封装到map中(3)将表中将表中记录封装到javabean对象中 访问数据库的技术叫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类型 sqlTypegetXXX()获取参数值

如何调用这个存储过程 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,则返回0first()将指针移到当前记录的第一行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(); } } }

8 ↩︎

16 ↩︎

24 ↩︎

32 ↩︎

8 ↩︎

16 ↩︎

24 ↩︎

32 ↩︎

最新回复(0)