【0】README
1) 本文部分文字描述和source code 均转自 core java volume 2 , 旨在理解 java数据库编程——执行查询操作 的基础知识 ;
2) 本文和 java数据库编程——执行查询操作(二) 是姊妹篇, 共同组成了 java数据库编程——执行查询操作的全部内容, for java数据库编程——执行查询操作(二), please visit http://blog.csdn.net/PacosonSWJTU/article/details/50629580
3)for database connection config, please visit : https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter4/database.properties
【1】预备语句(prepared statement)
1) 预备语句(prepared statement): 它是 Statement 语句对象;
2)problem+solution:
2.1)problem:我们没有必要在每次开始一个查询是都建立新的查询语句;
select books.price, books.title
from books, publishers
where books.publisher_id = publishers.publisher_id
and publishers.name = the name from the list box2.2)solution: 而是准备一个带有宿主变量的查询语句,每次查询时只需要为该变量填入不同的字符串就可以反复多次使用该语句;
String publisherQuery =
“select books.price, books.title ” +
“from books, publishers ” +
“where books. …. and publishers.name = ?” (干货——预备语句中的宿主变量?)
3)PreparedStatement set 方法: 在执行预备语句前, 必须使用 set 方法将变量 绑定到实际的值上;
stat.setString(1, publisher);
除非使用 set 或者 clearParameters 方法,否则所有宿主变量的绑定都不会改变;
4)价格更新操作可以有 update 语句实现:
4.1)请注意: 我们调用的是 executeUpdate 方法, 而非executeQuery 方法, 因为 update 语句不返回结果集。 executeUpdate 的返回值为 被修改过的行数;(干货——executeUpdate 的返回值为 被修改过的行数)
int r = stat.executeUpdate();
5)看个荔枝:(低效率的java 数据库查询代码)
select books.price, books.title from books, booksAuthors, authors, publishers where authors.author_id = booksAutors.author_id and booksAuthors.isbn=books.isbn and books.publisher_id=publisher.publisher_id and authors.name=? and publisher.name=?
对以上java数据库查询代码的分析(Analysis)
- A1)在相关的 Connection对象关闭后, PreparedStatement 对象就变得无效了。 不过, 许多数据库通常都会自动缓存预备语句。如果相同的查询被预备了两次, 数据库通常会直接重用查询策略;
- A2)许多coders 都不喜欢用 如此复杂的sql 语句,比较常见的方法是使用大量的 java 代码来迭代多个结果集, 但是这种方法是低效的; (干货——比较常见的方法是使用大量的 java 代码来迭代多个结果集, 但是这种方法是低效的)
- A3)通常,使用数据库的查询代码要比使用 java 代码好得多——这是数据库的一个优点, 一般而言,可以使用 sql 语句解决的问题,就不要使用 java 程序; (干货——一般而言,可以使用 sql 语句解决的问题,就不要使用 java 程序)
6) 利用预备语句插入和查询的荔枝
- 6.1)for full source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter4/execute_select/MyGetPrimaryKey.java
- 6.2)key source code at a glance
public static Connection getConnection() throws IOException, SQLException
{
Properties prop = new Properties();
try(InputStream in = Files.newInputStream(Paths.get(cur_dir + "database.properties")))
{
prop.load(in);
}
String drivers = prop.getProperty("jdbc.drivers");
if(drivers != null)
{
System.setProperty("jdbc.drivers", drivers); // register drivers for accessing database
}
String url = prop.getProperty("jdbc.url");
String user = prop.getProperty("jdbc.username");
String pass = prop.getProperty("jdbc.password");
return DriverManager.getConnection(url, user, pass);
}
// PreparedStatement for query operation
public static void main3(String[] args) throws SQLException, IOException
{
try
{
try(Connection conn = getConnection())
{
// String sql = "insert employee(name, salary, address) values('zhangsan',1000,'beijing')";
String sql = "select * from employee where id > ?";
PreparedStatement stat = conn.prepareStatement(sql);
stat.setInt(1, 12);
ResultSet rs = stat.executeQuery();
// attention for not writing stat.executeQuery(sql);
while(rs.next())
{
System.out.println(rs.getInt(1) + ", " + rs.getString(2) + ", " + rs.getDouble(3) + ", " + rs.getString(4));
}
}
}catch(Exception e)
{
e.printStackTrace();
}
}
// PreparedStatement for insert operation
public static void main2(String[] args) throws SQLException, IOException
{
try
{
try(Connection conn = getConnection())
{
// String sql = "insert employee(name, salary, address) values('zhangsan',1000,'beijing')";
String sql = "insert into employee(name,salary,address) values(?,?,?)";
//Statement stat = conn.createStatement();
PreparedStatement stat = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
String[] names = {"lisi", "wangwu", "zhaoliu"};
double[] salary = {120, 110, 999};
String[] address = {"chengdu", "shanghai", "shenzheng"};
for (int i = 0; i < address.length; i++)
{
// 除非使用 set 或者 clearParameters 方法,否则所有宿主变量(?)的绑定都不会改变;
stat.setString(1, names[i]);
stat.setDouble(2, salary[i]);
stat.setString(3, address[i]);
stat.executeUpdate();
// attention for not writing stat.executeUpdate(sql);
}
sql = "select * from employee";
ResultSet rs = stat.executeQuery(sql);
while(rs.next())
{
System.out.println(rs.getInt(1) + ", " + rs.getString(2) + ", " + rs.getDouble(3) + ", " + rs.getString(4));
}
}
}catch(Exception e)
{
e.printStackTrace();
}
}
其中, database.properties 文件内容如下(后面不在累述):
jdbc.drivers=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testCoreJava
jdbc.username=root
jdbc.password=root6.3)relative printing results as follows
【2】读写 LOB(Large OBject)
1)大对象(LOB):许多数据库还存储大对象, 如图片和其它数据; (干货——LOB定义)
- 1.1)BLOB+CLOB:二进制大对象称为BLOB, 字符型大对象被称为 CLOB;
- 1.2)要读取 LOB: 需要执行 select 语句,然后在 ResultSet 上调用 getBlob 或getClob 方法, 这样就可以获得 Blog 或 Clob 类型的对象了;
- 1.3)要从 Blob 中获取二进制数据:可以调用 getBytes 或 getInputStream ;
- 1.4)获取Clob的字符数据:类似地, 如果获取了 Clob对象, 那么就可以调用getSubString 或 getCharacterStream方法来获取其中的字符数据;
2)看个荔枝: 如何将图片保存到数据库和如何从数据库获取图片并保存到本地 (干货荔枝——如何向数据库插入图片和从数据库中获取图片)
Attention)
- A1)通过JDBC将图片插入到数据库和从数据库取出图片本保存到本地的idea, 参见 http://blog.csdn.net/pacosonswjtu/article/details/50628628
A2)荔枝中 关于存储图片到本地的代码转自 http://www.codejava.net/java-se/jdbc/read-file-data-from-database-using-jdbc
A3)for full source code, please visit : https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter4/execute_select/JDBCReadWriteImage.java
- A4)key source code at a glance :
package com.corejava.chapter4;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCReadWriteImage
{
private static String cur_dir = System.getProperty("user.dir") + File.separator +
"com" + File.separator + "corejava" + File.separator + "chapter4" + File.separator;
// insert and select blob obj
public static void main(String[] args)
{
try
{
try(Connection conn = getConnection())
{
// inserting starts.
String sql = "insert into employee(name, headportrait) values(?,?)";
PreparedStatement insertStat = conn.prepareStatement(sql);
insertStat.setString(1, "imageAdmin");
insertStat.setBlob(2, new FileInputStream(new File(cur_dir+"jdbc.jpg")));
if(insertStat.executeUpdate() != 0)
{
System.out.println("successful inserting!");
}
else
{
System.out.println("failed inserting!");
}
// inserting ends.
// query starts.
sql = "select headportrait from employee where name = 'imageAdmin'";
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
int i = 1;
while(rs.next())
{
Blob blob = rs.getBlob(1);
InputStream instream = blob.getBinaryStream();
OutputStream outstream = new FileOutputStream(new File(cur_dir + "blog" + (i++) +".jpg"));
byte[] buffer = new byte[1024];
int readLength = -1;
while((readLength = instream.read(buffer)) != -1)
{
outstream.write(buffer, 0, readLength);
}
System.out.println("successful query and saving the file !");
}
// query ends.
stat.close();
conn.close();
}
}catch(Exception e)
{
e.printStackTrace();
}
}
public static Connection getConnection() throws IOException, SQLException
{
Properties prop = new Properties();
try(InputStream in = Files.newInputStream(Paths.get(cur_dir + "database.properties")))
{
prop.load(in);
}
String drivers = prop.getProperty("jdbc.drivers");
if(drivers != null)
{
System.setProperty("jdbc.drivers", drivers); // register drivers for accessing database
}
String url = prop.getProperty("jdbc.url");
String user = prop.getProperty("jdbc.username");
String pass = prop.getProperty("jdbc.password");
return DriverManager.getConnection(url, user, pass);
}
}
- A5) relative printing results as follows: