使用预处理语句
Java提供了效率更高的数据库处理操作,就是PreparedStatement对象.
使用预处理语句的优点
由于连接器对象调用createStatement()
产生一个对象然后调用executeQuery(String sql)
方法是将SQL语句
发送到数据库然后数据库再将其编译成自己能明白的命令,当数据量大的时候就会影响执行的速度,那么通过预处理的目的就是将SQL语句
先进行编译后在发送到数据库,从此提高执行效率
方法就是使用Connection和某个数据库建立连接后的对象调用preparedStatement(String sql)
方法对SQL语句进行预编译处理
String sql = "select * from mess where height < ? and name = ? ";
PreparedStatement presql = con.preparedStatement(sql);
使用通配符
在SQL语句进行预处理时可以使用通配符"?"(英文问号)来代替字段的值就如上面的代码
之后可以通过预处理对象进行对值的设置例如
presql.setFloat(1,1.76f)
presql.setString(2,"同学")
预处理语句设置通配符"?"的常用方法(int preparedIndex 表示第几个通配符)
- void setDate(int preparedIndex, Date x) //设置日期
- void setDouble(int preparedIndex, double x) //设置双浮点
- void set基本数据类型…
通过使用预处理语句来使用过通配符对表进行操作的例子
import Chapter_14.GetDatabaseConnection;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Example14_5 {
public static void main(String[] args) {
PreparedStatement presql;
Connection connection = null;
ResultSet resultSet;
try {
connection = GetDatabaseConnection.connectDB("book", "root", "");
} catch (Exception e) {
e.printStackTrace();
}
if (connection == null) return;
String sql = "select * from mybooklist where name like ?"; //选择表中含有?的记录
try {
presql = connection.prepareStatement(sql);
presql.setString(1, "%大学%"); //设置通配符
resultSet = presql.executeQuery(); //将预编译语句传给数据库
while (resultSet.next()) {
String ISBN = resultSet.getString(1);
String name = resultSet.getString(2);
String price = resultSet.getString(3);
String date = resultSet.getString(4);
System.out.println(ISBN + "/" + name + "/" + price + "/" + date);
System.out.println();
}
resultSet.close(); //关闭
} catch (SQLException e) {
e.printStackTrace();
}
}
}
运行结果
C:\Users\Administrator\.IntelliJIdea2019.3\config\jdbc-drivers\MySQL Connector\J 8\8.0.15\mysql-connector-java-8.0.15.jar" Chapter_14.Part_4.Example14_5
3-565346-462/我的大学/34.5/2020-04-05
7-352-01465/大学日语/58.5/2020-05-01
通用查询
通用查询的目的是创建一个类,用户输入数据库名,SQL语句传递给该类对象,然后通过一个二维数据返回查询到的记录
为了编写通用查询,需要知道数据库表的字段名以及列数,所以通过程序中的结果集ResultSet对象调用ResultSetMetaDate类
的对象getColumnCount()方法返回结果集列的数目
ResultSetMetaData metaData = rs.getMetaData();
获取对象后可以调用getColumnCount()
方法返回结果集的列数
int columnCoount = metaData.getColumnCount();
调用getColumnName(int i)
方法返回第i列的名称
String columnName = getColumnName(1); //返回第一列的名称
具体例子
import java.sql.*;
public class Query {
String databaseName = ""; //数据库名称
String SQL;
String[] columnName;
String[][] record;
public Query() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName.trim(); //trim()去除两端多余空格
}
public void setSQL(String SQL) {
this.SQL = SQL;
}
public String[] getColumnName() {
if (columnName == null) {
System.out.println("先查询记录");
return null;
}
return columnName;
}
public String[][] getRecord() {
startQuery();
return record;
}
private void startQuery() {
Connection connection;
Statement sql;
ResultSet resultSet;
String url = "jdbc:mysql://localhost:3306/" + databaseName + "?useSSL = false&serverTimezone = GMT";
try {
connection = DriverManager.getConnection(url, "root", ""); //连接数据库
sql = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); //设置可滚动模式
resultSet = sql.executeQuery(SQL);
ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); //获取结果集的数据
int columnCount = resultSetMetaData.getColumnCount();
columnName = new String[columnCount]; //列名称数数组长度初始化
for (int i = 1; i <= columnCount; i++) { //对列名称数组进行赋值
columnName[i - 1] = resultSetMetaData.getColumnName(i);
}
resultSet.last(); //将游标移到最后
int row = resultSet.getRow(); //返回结果集记录的数目
record = new String[row][columnName.length]; //
resultSet.beforeFirst(); //将游标移到第一行前
int i = 0;
while (resultSet.next()) {
for (int j = 1; j <= columnName.length; j++) {
record[i][j - 1] = resultSet.getString(j); //i为行j为列
}
i++;
}
connection.close(); //关闭
} catch (SQLException e) {
e.printStackTrace();
}
}
}
import javax.swing.*;
public class Example14_6 {
public static void main(String[] args) {
String[] name;
String[][] record;
JTable jTable;
JFrame jFrame;
Query query = new Query();
query.setDatabaseName("book");
query.setSQL("select * from mybooklist");
record = query.getRecord();
name = query.getColumnName();
jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setBounds(300, 300, 500, 300);
jFrame.setVisible(true);
jTable = new JTable(record, name);
jFrame.add(new JScrollPane(jTable));
jFrame.validate();
}
}
运行结果
虚拟存储器管理
虚拟存储器的引入
-
局部性原理
存储管理策略的基础是局部性原理为进程往往会不均匀地、高度局部化地访问主存。
分为时间局部性和空间局部性
时间局部性
//指最近被访问的存储位置,很可能不久的将来还要访问,如循环、栈等。
空间局部性
//当访问了某个位置后,很可能还要访问其附近的位置,如访问数组、代码顺序执行等。 -
虚拟存储器的定义
一个作业在运行之前,没有必要全部装入主存,而仅将当前要运行的那部分页面或段先装入主存启动运行,其余部分暂时留在磁盘上。 -
虚拟存储器的实现
请求分页系统
请求分段系统
请求分页中的硬件支持
- 请求分页的页表机制
请求分页的页表机制是在纯分页的页表机制上形成的,由于只将应用程序的一部分调入主存,但还有一部分仍在磁盘上,故需在页表中再增加若干项,如状态位、访问字段、辅存地址等供程序(数据)在换进、换出时引用。
- 缺页中断机构
在请求分页系统中,每当所要访问的页面不在主存时,便要产生一个缺页中断,请求操作系统将所缺页调入主存。它与一般中断的主要区别在于:缺页中断在指令执行期间产生和处理中断信号,而一般中断在一条指令执行完后检查和处理中断信号;缺页中断返回到该指令的开始重新执行该指令,而一般中断则返回到该指令的下一条指令执行。
- 地址转换机构
请求分页系统中的地址转换机构是在分页系统的地址转换机构的基础上,为实现虚托存储器而增加了某些功能后形成的,如产生和处理缺页中断、从主存中换出一页等。
页面置换算法
- 最佳置换算法
最佳(Optimal)置换算法是一种理想化的算法,性能最好,但实际上难以实现,所以这算法通常用来评价其他算法。
- 先进先出置换算法
先进先出(FIFO)置换算法总是淘汰最先进入内存的页面。其算法实现简单,是一种最直观,也是性能最差的算法。
- 最近最久使用置换算法
最近最久未便用(Least Recently Used,LRU)置换算法是选择最近最久未使用的页面于以淘汰,系统在每个页面设置一个访问字段,用以记录这个页面自上次被访问以来所经历的时间T,当要淘汰一个页面时,选择T最大的页面。
- 最近未用置换算法
最近未用Not Used Recently,NUR)置换算法将最近一段时间未引用过的页面换出,是一种LRU的近似算法。
CET4P191
- enable
- vitamin
- vivid
- keyboard
- grateful
- convenience
- assignment
- deserve
- reproduce
- principal
- refrigerator
- outset