当文本数据内容超过64K字节时,可以称为大文本数据,大文本数据也称为CLOB数据。在MySQL中,提供了LONGTEXT类型的字段用来存储大文本数据。
课程案例shop数据库的goods(产品表)的brief字段就是大文本数据字段,可以存储4G以内的文本数据。写入大文本数据时,需要通过I/O流的方式从文本文件中读取文本内容。
针对大文本数据,PreparedStatement接口提供了如下几个方法用于写入大文本数据:
void setAsciiStream(int parameterIndex, InputStream x, int length)
该方法将指定的输入流写入数据库文本字段中。参数parameterIndex表示字段所在记录的列号。参数InputStream为输入流。参数length表示输入流的长度。
void setBinaryStream(int parameterIndex, InputStream x, int length)
该方法将指定的输入流写入数据库的二进制字段中。参数parameterIndex表示字段所在记录的列号。参数InputStream为输入流。参数length表示输入流的长度。
大文本数据写入数据库后,在查询时需要使用ResultSet接口将数据读出来。ResultSet接口提供了如下几个方法用于读取大文本数据:
InputStream getAsciiStream(int columnIndex)
该方法根据记录的列编号返回文本输入流。参数columnIndex表示结果集当前光标所在行的列号。
InputStream getAsciiStream(String columnLabel)
该方法根据记录的列名称返回文本输入流。参数columnLabel表示结果集当前光标所在行的列名称。
Clob getClob(int columnIndex)
该方法根据记录的列编号返回Clob对象。参数columnIndex表示结果集当前光标所在行的列号。
Clob getClob(String columnLabel)
该方法根据记录的列名称返回Clob对象。参数columnIndex表示结果集当前光标所在行的列名称。
InputStream getBinaryStream (int columnIndex)
该方法根据记录的列编号返回二进制数据输入流。参数columnIndex表示结果集当前光标所在行的列号。
InputStream getBinaryStream(String columnLabel)
该方法根据记录的列名称返回二进制数据输入流。参数columnLabel表示结果集当前光标所在行的列名称。
Blob getBlob(int columnIndex)
该方法根据记录的列编号返回Blob对象(二进制大数据对象)。参数columnIndex表示结果集当前光标所在行的列号。
Blob getBlob(String columnLabel)
该方法根据记录的列名称返回Blob对象(二进制大数据对象)。参数columnIndex表示结果集当前光标所在行的列名称。
案例1:在goods表中插入一条记录,goods表的brief是LONGTEXT类型字段,该字段的值需要从文本文件读入。
在demo包下新建SqlDemoTest7类。代码如下:
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @ClassName: SqlDemoTest7
* @Description: 数据库编程(处理大文本数据)案例1
* @author 编程训练营
* @date
*
*/
public class SqlDemoTest7 {
// 定义JDBC加载路径
static String jdbc = "com.mysql.cj.jdbc.Driver";
// 定义MySQL数据库的连接地址
static String mysqlurl = "jdbc:mysql://localhost:3306/shop?serverTimezone=GMT%2B8";
// 定义MySQL数据库的用户名
static String username = "root";
// 定义MySQL数据库的用户名登录密码
static String password = "~123456q";
/**
* @Title: main
* @Description: Java程序入口main方法
* @param @param args 参数
*
* @return void 返回类型 @throws
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
Connection conn = null;
PreparedStatement prepartStatement = null;
try {
// 加载JDBC驱动
Class.forName(jdbc);
// 连接数据库
conn = DriverManager.getConnection(mysqlurl, username, password);
if (null != conn) {
System.out.println(conn);
// 向shoper表中插入一条记录
String sql = "insert into goods(id,name,categoryId,photo,shoperId,price,status,createDate,brief)"
+ "values(?,?,?,?,?,?,?,?,?)";
// 实例化PreparedStatement对象
prepartStatement = conn.prepareStatement(sql);
// 设置id字段的值
prepartStatement.setString(1,"0001");
// 设置name字段的值
prepartStatement.setString(2,"电脑");
// 设置categoryId字段的值
prepartStatement.setString(3,"010");
// 设置photo字段的值
prepartStatement.setString(4,"");
// 设置photo字段的值
prepartStatement.setString(5,"01");
// 设置price字段的值
prepartStatement.setDouble(6, 0.0);
// 设置status字段的值
prepartStatement.setInt(7, 0);
// 设置createDate字段的值
java.util.Date date = new java.util.Date();
java.sql.Date sqldate = new java.sql.Date(date.getTime());
prepartStatement.setDate(8,sqldate);
// 定义一个File对象,准备从文件中读取数据
File file = new File("d:" + File.separator + "temp.txt");
InputStream input = new FileInputStream(file);
prepartStatement.setAsciiStream(9, input, file.length());
// 执行SQL语句
int row = prepartStatement.executeUpdate();
if( row == 1 )
{
System.out.println("goods表添加记录成功");
}
else
{
System.out.println("goods表添加记录失败");
}
prepartStatement.close();
conn.close();
} else {
System.out.println("数据库连接失败");
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}执行大文本数据的写入必须使用PreparedStatement接口,PreparedStatement接口的setDate()方法和Statement接口的setDate()方法有所不同,它需要传入java.sql.Date类型的对象。
程序使用FileInputStream将文本文件读取进来,然后通过PreparedStatement接口的setAsciiStream()方法将文件内容写入到对应的大文本字段中。
程序执行结果如下图所示:
大文本文件写入完成后,在读取数据库记录时,可以使用ResultSet接口的读取大文本数据的方法将文本内容读取出来。
案例2:查询案例1写入的记录,并将记录内容输出到控制台。
在demo包下新建SqlDemoTest8类。代码如下:
package demo;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.Scanner;
/**
* @ClassName: SqlDemoTest8
* @Description: 数据库编程(处理大文本数据)案例2
* @author 编程训练营
* @date
*
*/
public class SqlDemoTest8 {
// 定义JDBC加载路径
static String jdbc = "com.mysql.cj.jdbc.Driver";
// 定义MySQL数据库的连接地址
static String mysqlurl = "jdbc:mysql://localhost:3306/shop?serverTimezone=GMT%2B8";
// 定义MySQL数据库的用户名
static String username = "root";
// 定义MySQL数据库的用户名登录密码
static String password = "~123456q";
/**
* @Title: main
* @Description: Java程序入口main方法
* @param @param args 参数
*
* @return void 返回类型 @throws
*/
public static void main(String[] args) {
Connection conn = null;
Statement statement = null;
try {
// 加载JDBC驱动
Class.forName(jdbc);
// 连接数据库
conn = DriverManager.getConnection(mysqlurl, username, password);
if (null != conn) {
System.out.println(conn);
// 获取表记录数的SQL语句
String sql = "select * from goods where id='0001'";
// 实例化Statement对象
statement = conn.createStatement();
// 执行SQL查询语句
ResultSet resultset = statement.executeQuery(sql);
if (null != resultset) {
while( resultset.next() )
{
// 获取id字段内容
String id = resultset.getString("id");
// 获取name字段内容
String name = resultset.getString("name");
// 获取categoryId字段内容
String categoryId = resultset.getString("categoryId");
// 获取photo字段内容
String photo = resultset.getString("photo");
// 获取shoperId字段内容
String shoperId = resultset.getString("shoperId");
// 获取price字段内容
BigDecimal price = resultset.getBigDecimal("price");
// 获取status字段内容
int status = resultset.getInt("status");
// 获取createDate字段内容
Date createDate = resultset.getDate("createDate");
// 读取大文本数据
InputStream input = resultset.getAsciiStream("brief");
StringBuilder sbuilder = new StringBuilder();
Scanner scanner = new Scanner(input);
while( scanner.hasNext() )
{
sbuilder.append(scanner.next());
sbuilder.append("\n");
}
System.out.printf("-----输出第%d条记录-----\n",resultset.getRow());
System.out.println("id:" + id + ";");
System.out.println("name:" + name + ";");
System.out.println("categoryId:" + categoryId + ";");
System.out.println("photo:" + photo + ";");
System.out.println("price:" + price.toString() + ";");
System.out.println("status:" + status + ";");
System.out.println("createDate:" + createDate.toString() + ";");
System.out.println("brief:" + sbuilder.toString() + ";");
System.out.println("-------------------------------");
}
resultset.close();
} else {
System.out.println("SQL语句执行失败");
}
statement.close();
conn.close();
} else {
System.out.println("数据库连接失败");
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}ResultSet的getAsciiStream()会返回与大文本字段对应的输入流InputStream,程序可以通过InputStream来读取大文本字段内容。
程序也可以调用ResultSet接口的getClob()方法来读取大文本字段内容,getClob()方法会返回Clob对象,该对象也包含一个getAsciiStream()方法,用于获取InputStream输入流。Clob是对大文本数据的一个封装操作接口,该接口在java.sql包内,Clob接口具体内容和使用方法可以参考Java API文档。
程序执行结果如下图所示:
