JDBC驱动有两个类负责与数据库建立连接:DriverManager和JDBC Driver。
SPM(服务提供商机制):DriverManager从已经加载的JDBC驱动程序库中选择合适驱动,或者在当前应用的同一类加载器加载使用过的驱动。
在SPM机制下,要求META-INF/services/java.sql.Driver下指定驱动,内容如:com.mysql.jdbc.Driver
JDBC URL格式为jdbc:子协议:数据库定位器,例如jdbc:mysql://机器名/数据库名、jdbc:derby://机器名/数据库名、jdbc:oracle:thin@机器名:端口名:数据库名
DriverManager.getConnection(url [,user] [,password])
三种类型的Statement:Statement、PreparedStatement、CallableStatement
三种执行SQL语句的方法:
executeQuery():对于单个结果集
executeUpdate():执行增删改或DDL执行返回更新计数
execute():返回多个结果集、多个更新计数或两者结合的语句
ResultSet结果集,next()光标向下移动,getXXX()如rs.getString(“title”)或rs.getString(2)
1.Statement:
conn=java.sql.DriverManager.getConnection(“jdbc:mysql://localhost:3306/sample”,”root”,”mysql123”);
sqlStmt=conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY);
sqlRst=sqlStmt.executeQuery(sqlQuery);
...
<%=sqlRst.getString(“customerid”)%>
2.PrepareStatement:
PrepareStatement pstmt = con.prepareStatement(“UPDATE table1 SET m = ? WHERE x = ?”);
3.CallableStatement:
(1)getCustomerName.sql:
CREATE DEFINER = ’root’@’localhost’ PROCEDUER ‘getCustomerName’ (
IN ‘ID’ VARCHAR(6),
OUT ‘Name’ VARCHAR(20)
)
...
BEGIN
...
END
(2)CallStatementDemo.java:
CallableStatement stmt = conn.prepareCall(“{call getCustomerName(?,?)}”);
stmt.setString(1,”1”);
stmt.registerOutParameter(2,java.sql.Types.VARCHAR);
stmt.execute();
String custName = stmt.getString(2);
4.ResultSet
ResultSet.TYPE_FORWARD_ONLY:只能调用next()向前遍历
ResultSet.TYPE_SCROLL_INSENSITIVE:结果集是快照,其他用户对数据库更改不会影响此结果集
ResultSet.TYPE_SCROLL_SENSITIVE:结果集是引用,其他用户对数据库更改会影响此结果集
ResultSet.CONCUR_READ_ONLY:只读数据
ResultSet.CONCUR_UPDATEABLE:数据可更新到数据库
对ResultSet包含数据的操作即对光标的操作,常见操作方法:
beforeFirst()、afterLast()、first()、last()、absolute(int row)、relative(int row)、previous()、next()、getRow()
Demo:
sqlStmt = conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_UPDATEABLE);
sqlRst = sqlStmt.executeQuery(sqlQuery);
sqlRst.last();
sqlRst.updateString(“adress”,”中关村1号”);
sqlRst.updateRow();
Blob:
ResultSet获取流的方法:getBinaryStream/getAsciiStream/getUnicodeStream
5.RowSet
RowSet是离线数据集,不必保持数据库连接,有效利用计算机的内存,减轻数据库服务器的负担
五个子类:CachedRowSet最常用,WebRowSet、FilteredRowSet、JoinRowSet直接或间接继承于它,JdbcRowSet是连接类型的,通常用来包装驱动不支持ResultSet滚动和更新的场景
RowSet获取数据的两种方法:(1)setUrl()、setCommand()之后execute();(2)populate(ResultSet)
Demo(利用CachedRowSet进行简单的分页操作):
...
<%
CachedRowSet rt = new (com.sun.rowset.)CachedRowSetImpl();
strOP = request.getParameter(“op”);
If(strOP ==null){
initPage = 1;
...
rt.setUrl(“jdbc:mysql://localhost:3306/sample”);
rt.setCommand(“SELECT customerid,phone FROM customer”);
rt.execute();//为了获取记录条数
intRowCount = rt.size();
intPageCount = (intRowCount+intPageSize-1)/intPageSize;
rt.release();
rt.setPageSize(intPageSize);
rt.execute();
session.setAttribue(“data”,rt);
...
}else{
...
rt = (CachedRowSet) session.getAttribue(“data”);
...
If(strOP.equals(“pre”)){
...
rt.priviousPage();
}else{
...
rt.nextPage();
}
}
%>
...
6.连接池和数据源
基于连接池的数据库访问体系结构中,通过JDBC获取的资源对象(Connection、Statement、ResultSet等)不再是直接由驱动程序访问数据库产生,而是通过连接池来提供
通过javax.sql.ConnectionPooledDataSource获取连接池,通过javax.sql.DataSource请求数据库资源
连接池和数据源的信息都储存在JNDI里,它提供一个查询和使用远程服务的机制。
InitialContext context = new InitialContext();
DataSource dataSource = (DataSource)context.lookup(“sample”);//已经省略在Netbeans的GlasssFish Server新建连接池和数据源,数据源的JNDI名称为sample
conn = dataSource.getConnection();