select count 1from 表;采用哪个resultsethandler

16933人阅读
计算机技术与使用(9)
用 JDBC(包括 Oracle JDBC 扩展)时,没有直接的(即标准的)方法可以使用 ResultSet 或 RowSet 获得查询所返回的行数。但是可以通过很少几行代码使用 Scrollable ResultSet 或 Cached RowSet 来获得此结果。以下列出了可以使用的不同方法的详细内容。
一种方法是在实际查询前执行 &SELECT COUNT(*)...&。这意味着数据库引擎必须对相同的数据进行两次分析(一次用于计数,一次用于数据本身)。
第二种方法使用 JDBC 2.0:
一种使用 Scrollable ResultSet
另一种使用 Cached RowSet 与普通(不可滚动)ResultSet 的组合。
JDBC 方法允许我们获得查询的行数而不必扫描所有的行或执行单独的 SELECT COUNT(*)。移到 Scrollable ResultSet/Cached RowSet 的尾部并获取其位置(resultset.last()/cachedRowset.last() 和 resultset.getRow()/cachedRowset.getRow()),即可完成所需的工作。RowSet 扩展了 ResultSet 接口,因此我们可以使用普通的 ResultSet(而不是可滚动的)。使用 Scrollable ResultSet 的说明:
如果 ResultSet 非常大,则 resultset.last() 有可能是非常费时的操作,因为它将使用服务器端的更多资源。因此,除非确实需要可滚动结果集,应避免使用这种方法。
Oracle JDBC 驱动程序将使用 resultset.getRow() 返回正确的计数。但是其他供应商的实现方法可能会由 resultset.getRow() 返回零。
以下是早先提及方法的代码段。
使用 SQL 查询:
................// Get a record count with the SQL StatementStatement stmt = connection.createStatement();ResultSet rs = stmt.executeQuery(&SELECT COUNT(*) AS rowcount FROM
emp&);rs.next();// Get the rowcount column value.int ResultCount = rs.getInt(rowcount) ;rs.close() ;
...............
..............
sqlString = &SELECT * FROM emp&;
// Create a scrollable ResultSet.
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);rs = stmt.executeQuery(sqlString);
// Point to the last row in resultset.
rs.last();
// Get the row position which is also the number of rows in the ResultSet.
int rowcount = rs.getRow();
System.out.println(&Total rows for the query:&+rowcount);
// Reposition at the beginning of the ResultSet to take up rs.next() call.
rs.beforeFirst();
................
.........................
ResultSet rs =........................
// Create and initialize Cached RowSet object.
OracleCachedRowSet ocrs = new OracleCachedRowSet();
// Create a string that has the SQL statement that gets all the records.
String sqlString = &SELECT empno FROM emp&;
// Create a statement, resultset objects.
stmt = conn.createStatement();
rs = stmt.executeQuery(sqlString);
// Populate the Cached RowSet using the above Resultset.
ocrs.populate(rs);
// Point to the last row in Cached RowSet.
ocrs.last();
// Get the row position which is also the number of rows in the Cached
// RowSet.
int rowcount = ocrs.getRow();
System.out.println(&Total rows for the query using Cached RowSet: &+
rowcount);
// Close the Cached Rowset object.
if (ocrs != null)
ocrs.close();.............
单击查看全部可运行的源代码。
将全部源代码 () 拷贝到一个目录并将其保存为 CountResult.java 文件。
编辑 CountResult.java 并在类构造器中更改设置数据库参数的行。// Connect to the local database.conn = DriverManager.getConnection(&jdbc:oracle:thin:@insn104a.:1521:ora9idb&,&scott&, &tiger&);注意:以下是设置数据库参数的格式。conn = DriverManager.getConnection(&jdbc:oracle:thin:@&hostname&:&port&:&sid&&,&scott&, &tiger&); 其中 &hostname& 是运行数据库的主机名。其中 &port& 是数据库监听的端口号。默认为 1521。 其中 &sid& 是 Oracle 数据库的 sid。
在拷贝目录的命令提示符处,将 classpath 设置为包括 Oracle JDBC 驱动程序类:(classes12.zip 或 classes12.jar)以及当前目录。
现在,编译 CountResult 类。 javac CountResult.java
运行该类。java CountResult此操作使用 Scrollable ResultSet 和 Cached RowSet 来显示检索的查询行数。检查数据库表 'emp' 中的计数,进行验证。&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:229775次
积分:3730
积分:3730
排名:第5842名
原创:135篇
转载:20篇
评论:51条
(2)(1)(1)(1)(1)(3)(2)(1)(1)(1)(1)(2)(2)(1)(7)(4)(6)(6)(3)(2)(3)(1)(3)(11)(5)(3)(1)(2)(11)(1)(1)(1)(1)(2)(1)(9)(6)(20)(13)(12)(1)Java进阶学习第十九天——dbutils与案例 - 博客频道 - CSDN.NET
lutianfei的专栏
分类:JavaJava进阶
元数据(metaData)
指数据库中 库、表、列的定义信息
DataBaseMetaData 数据库元数据
获取一个DataBaseMetaData
Connection接口中定义了一个方法 getMetaData();
Connection.getMetaData()
通过DataBaseMetaData获得 数据库连接的基本参数
getURL():返回一个String类对象,代表数据库的URL。
getUserName():返回连接当前数据库管理系统的用户名。
getDriverName():返回驱动驱动程序的名称。
getPrimaryKeys(String catalog, String schema, String table):返回指定表主键列的结果集
获得数据库、表、列、主键、外键 定义信息
getColumns
getPrimaryKeys
String driverName = dmd.getDriverName(); //获取驱动名称
String userName = dmd.getUserName();//获取用户名
String url = dmd.getURL();//获取url
String databaseProductName = dmd.getDatabaseProductName(); //获取数据库名称
String databaseProductVersion = dmd.getDatabaseProductVersion();//获取数据库版本.
ResultSet getPrimaryKeys(String catalog,String schema,String table)
获取表中主键相关描述,每个主键列描述都有以下列:
TABLE_CAT String =& 表类别(可为 null)
TABLE_SCHEM String =& 表模式(可为 null)
TABLE_NAME String =& 表名称
COLUMN_NAME String =& 列名称
KEY_SEQ short =& 主键中的序列号(值 1 表示主键中的第一列,值 2 表示主键中的第二列)。
PK_NAME String =& 主键的名称(可为 null)
ParameterMetaData 参数元数据
参数元数据主要用于获取:sql语句中占位符的相关信息.
PreparedStatement . getParameterMetaData()
获得代表PreparedStatement元数据的ParameterMetaData对象。
getParameterCount():获得指定参数的个数
getParameterTypeName(int param) :获得指定参数的sql类型
注意:在获取参数类型时会产生异常
java.sql.SQLException: Parameter metadata not available for the given statement
在url后添加参数:jdbc : mysql:///day18?generateSimpleParameterMetadata=true
原因:是mysql驱动的支持问题。
ResultSetMetaData 结果集元数据(重点)
ResultSet. getMetaData()
获得代表ResultSet对象元数据的ResultSetMetaData对象。
getColumnCount() 返回resultset对象的列数
getColumnName(int column) 获得指定列的名称
getColumnTypeName(int column) 获得指定列的类型
public static void main(String[] args) throws SQLException {
Connection con = JdbcUtils.getConnection()
ResultSet rs = con.createStatement().executeQuery(
"select * from account")
// 得到结果集元数据
ResultSetMetaData rsmd = rs.getMetaData()
// System.out.println(rsmd.getColumnCount())
// System.out.println(rsmd.getColumnName(2))
// System.out.println(rsmd.getColumnTypeName(3))
int count = rsmd.getColumnCount()
for (int i = 1
System.out.print(rsmd.getColumnName(i)+"("+rsmd.getColumnTypeName(i)+")" + "\t")
System.out.println()
while (rs.next()) {
for (int i = 1
System.out.print(rs.getObject(i) + "\t\t")
System.out.println()
dbutils工具
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
简单说,它就是一个简单的jdbc封装工具,使用dbutils可以简化操作,要使用dbutils需要导入jar包。
JAR包: commons.dbutils-1.4.jar
mons.dbutils.QueryRunner — 核心
mons.dbutils.ResultSetHandler
mons.dbutils.DbUtils。
DBUtils学习
1、QueryRunner 框架核心类 ,所有数据库操作都是必须通过 QueryRunner 进行的,用于执行sql语句的类。
1.query 用于执行select
2.update 用于执行update delete insert
3.batch 批处理
2、ResultSetHandler 结果集封装接口,完成将ResultSet 结果集 封装为一个Java对象
用于定义结果集的封装
它提供九个实现类,可以进行不同的封装。
3、DbUtils 工具类 提供驱动管理、事务管理、释放资源等一系列公共方法
它提供关于关闭资源以及事务rollback,commit操作。
DbUtils里面的所有方法都是静态的。主要方法如下:
public static void close(…) throws java.sql.SQLException
DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
public static void closeQuietly(…)
这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
public static void commitAndCloseQuietly(Connection conn)
用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册*JDBC驱动程序*,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
Dbutlis详解
1.QueryRunner怎样获取
1.new QueryRunner()
如果是使用这种构造创建的QueryRunner,它的事务是手动控制。
2.new QueryRunner(DataSource ds);
如果是使用这种构造,它的事务是自动事务,简单说,一条sql一个事务。
2.QueryRunner中的三个核心方法
对于上述三个方法,它们提供很多重载。
如果QueryRunner在创建时,没有传递DataSource参数,那么在使用query,update,batch方法时,要传递Connection参数
如果QueryRunner在创建时,传递了Dataource参数,那么在使用query,update,batch方法时,不需要传递Connection参数。
怎样配套使用:
QueryRunner runner=new QueryRunner();
runner.query(Connection,sql,ResultSetHandler,Object… param);
runner.update(Connection,sql,Object…param);
runner.batch(Connection con,sql,Object[][] objs);
QueryRunner runner=new QueryRunner(DataSource ds);
runner.query(sql,ResultSetHandler,Object… param);
runner.update(sql,Object…param);
runner.batch(sql,Object [][] objs);
模仿QueryRunner
1.query方法模仿
public &T& T query(Connection con, String sql, MyResultSetHandler&T& mrs,Object... params) throws SQLException {
PreparedStatement pst = con.prepareStatement(sql);
ParameterMetaData pmd = pst.getParameterMetaData();
int count = pmd.getParameterCount();
for (int i = 1; i &= i++) {
pst.setObject(i, params[i - 1]);
ResultSet rs = pst.executeQuery();
return mrs.handle(rs);
2.update方法模仿
public int update(Connection con, String sql, Object... params) throws SQLException {
PreparedStatement pst = con.prepareStatement(sql);
ParameterMetaData pmd = pst.getParameterMetaData();
int count = pmd.getParameterCount();
for (int i = 1; i &= i++) {
pst.setObject(i, params[i - 1]);
int row = pst.executeUpdate();
pst.close();
ResulsetHandler九个实现类
ResultSetHandler接口:用于封装结果集.
该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler
接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
ArrayHandler, 将结果集中第一条记录封装到Object[]数组,数组中的每一个元素就是记录中的字段值。
ArrayListHandler, 将结果集中每一条记录封装到Object[],数组中的每一个元素就是记录中的字段值。在将这些数组装入到List集合。
BeanHandler(重点), 将结果集中第一条记录封装到一个javaBean中。
BeanListHandler(重点), 将结果集中每一条记录封装到javaBean中,在将javaBean封装到List集合。
ColumnListHandler, 将结果集中指定列的值封装到List集合.
MapHandler, 将结果集中第一条记录封装到Map集合中,集合的 key就是字段名称,value就是字段值
MapListHandler, 将结果集中每一条记录封装到Map集合中,集合的 key就是字段名称,value就是字段值,在将这些Map封装到List集合
KeyedHandler,在使用指定的列的值做为一个Map集合的key,值为每一条记录的Map集合封装。
ScalarHandler 进行单值查询 select count(*)
public class ResultSetHandlerImplTest {
public void fun1() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
Object[] obj = runner
.query("select * from account", new ArrayHandler());
System.out.println(Arrays.toString(obj));
public void fun2() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
List&Object[]& objs = runner.query("select * from account",
new ArrayListHandler());
for (Object[] obj : objs) {
System.out.println(Arrays.toString(obj));
public void fun3() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
Account obj = runner.query("select * from account",
new BeanHandler&Account&(Account.class));
System.out.println(obj);
public void fun4() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
List&Account& obj = runner.query("select * from account",
new BeanListHandler&Account&(Account.class));
System.out.println(obj);
public void fun5() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
List&Object& obj = runner.query("select * from account",
new ColumnListHandler("name"));
System.out.println(obj);
public void fun6() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
Map&String, Object& obj = runner.query("select * from account",
new MapHandler());
System.out.println(obj);
public void fun7() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
List&Map&String, Object&& obj = runner.query("select * from account",
new MapListHandler());
System.out.println(obj);
public void fun8() throws SQLException {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
Map&Object,Map&String,Object&& obj = runner.query("select * from account",
new KeyedHandler("name"));
System.out.println(obj);
public void fun9() throws SQLException{
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
long obj = (Long) runner.query("select count(*) from account",new ScalarHandler());
System.out.println(obj);
实现BeanHandler
public class MyBeanHandler implements MyResultSetHandler {
public MyBeanHandler(Class clazz) {
this.clazz =
public Object handle(ResultSet rs) throws SQLException {
Object obj = null;
Map&String, String[]& map = new HashMap&String, String[]&();
ResultSetMetaData md = rs.getMetaData();
int count = md.getColumnCount();
if (rs.next()) {
obj = clazz.newInstance();
for (int i = 1; i &= i++) {
map.put(md.getColumnName(i),
new String[] { rs.getString(md.getColumnName(i)) });
BeanUtils.populate(obj, map);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
dbutils综合练习
以下均为项目day19_2 代码说明。
登录成功后,访问到一个页面success.jsp,在页面上添加一个连接,就是客户信息的CRUD操作。
1.客户信息
varchar(40)
varchar(20)
varchar(10)
varchar(20)
varchar(40)
preference
varchar(100)
varchar(40)
description
varchar(255)
create table customer(
id varchar(40) primary key,
name varchar(20),
gender varchar(10),
birthday date,
cellphone varchar(20),
email varchar(40),
preference varchar(100),
type varchar(40),
description varchar(255)
2.搭建环境
JavaEE 三层结构
Servlet + JSP + JavaBean+jstl + DBUtils+ DAO + MySQL
导入jar包 :JSTL 、BeanUtils、DBUtils、C3P0、mysql驱动
创建包结构
cn.itcast.customer.web
cn.itcast.customer.service 业务层
cn.itcast.customer.dao 持久层
cn.itcast.customer.utils 工具包
cn.itcast.customer.domain 实体类
应用的jar文件
mysql驱动包
BeanUtil包
c3p0的配置文件
1.创建Customer这个javaBean
private String
private String
private String
private Date
private String
private String
private String
private String type;
private String
2.为了测试方便,向customer表中插入数据
insert into customer values("a11","tom","男","","","","吃,喝,玩","vip","good man");
insert into customer values("a11","fox","男","","","","吃,喝,玩","vip","good man");
insert into customer values("a11","james","男","","","","吃,喝,玩","vip","good man");
3.实现查询所有客户信息操作
1.在success.jsp页面添加连接
&a href="${pageContext.request.contextPath}/findAll"&查看所有客户信息&/a&
2.在CustomerFindAllServlet中调用service,在service中调用dao,最后得到一个List&Customer&。
3.在showCustomer.jsp页面展示客户信息
items="${cs}" var="c"&
& type="checkbox"&
&${c.id }&
&${c.name}&
&${c.gender }&
&${c.birthday }&
&${c.cellphone }&
&${c.email }&
&${c.preference }&
&${c.type }&
&${c.description }&
&&编辑&&&&&删除&&
4.删除操作
1.在showCustomer.jsp页面的删除连接上添加参数
&a href="${pageContext.request.contextPath}/delByid?id=${c.id}"&删除&/a&
2.创建一个CustomerDelByIdServlet,获取请求参数,调用service中删除方法.
问题:如果删除完成后,怎样处理?
需要重新跳转到查询所有的servlet中,在重新查询数据。
1.查询,做回显示
&a href="${pageContext.request.contextPath}/findById?id=${c.id}"&编辑&/a&
1.创建CustomerFindByIdServlet,得到要查询的id,调用service,得到Custonmer对象。
2.将customer对象存储到request域,请求转发到customerInfo.jsp页面。
3.在customerInfo.jsp页面展示客户信息
注意:客户的id不能修改,所以使用&input type="hidden"&
1.注意使用BeanUtils时的类型转换问题
2.注意编码问题
post: request.setCharacterEncoding("utf-8");
get:手动转换
new String(request.getParameter(name).getBytes("iso8859-1"),"utf-8");
3.进行修改操作
public void update(Customer c) throws SQLException {
String sql = "update customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=? where id=?"
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource())
runner.update(sql, c.getName(), c.getGender(), c.getBirthday(),
c.getCellphone(), c.getEmail(), c.getPreference(), c.getType(),
c.getDescription(), c.getId())
修改完成后,在重新查询一次
response.sendRedirect(request.getContextPath() + "/findAll");
解决关于回显示时的问题:
1.性别 应该使用radio
使用自定义标签
1.定义标签类
extends SimpleTagSupport
2.定义tld文件
&cn.itcast.customer.tag.GenderTag&
* 3.在页面上使用
* 1.使用taglib导入
* 2.使用`&my:sex gender="${c.gender}" /&`
使用虚拟主机可以将项目部署成顶级域名
1.在service.xml文件
1.端口修改为80
2.配置主机
&Host name=""
appBase="D:\java1110\workspace\day19_2"
unpackWARs="true" autoDeploy="true"&
&Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t &%r& %s %b" /&
&Context path="" docBase="D:\java1110\workspace\day19_2\WebRoot" /&
3.在hosts文件中配置
lutianfeiml
排名:第11253名
(70)(5)(2)(1)(4)(3)(41)(4)(3)(12)(4)(4)(4)(2)(1)(2)(1)(1)(0)Oracle(6)
1、自定义JDBC框架&——数据库元数据:DataBaseMetaData
元数据:数据库、表、列的定义信息。
DataBaseMetaData&& connection.getDatabaseMetaData()&&&&
获得代表DataBaseMetaData 对象元数据的DataBaseMetaData 对象。
&&&&DataBaseMetaData对象中的方法:
&&&&&&&&(1) getURL():返回一个String类对象,代表数据库的URL。
&&&&&&&&(2) getUserName():返回连接当前数据库管理系统的用户名。
&&&&&&&&(3) getDatabaseProductName():返回数据库的产品名称。
&&&&&&&&(4) getDatabaseProductVersion():返回数据库的版本号。
&&&&&&&&(5) getDriverName():返回驱动驱动程序的名称。
&&&&&&&&(6) getDriverVersion():返回驱动程序的版本号。
&&&&&&&&(7) isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
Demo样例:&获取数据库的元数据&
&&public&void&test1()&throws&SQLException{
&&&&&&&&Connection&conn&=&JdbcUtils_C3P0.getConnection();
&&&&&&&&DatabaseMetaData&meta&=&conn.getMetaData();
&&&&&&&&System.out.println(meta.getDatabaseProductName());
&&&&&&&&System.out.println(meta.getDatabaseMajorVersion());
&&&&&&&&System.out.println(meta.getDatabaseMinorVersion());
2、自定义JDBC框架&——数据库元数据:DataBaseMetaData
ParameterMetaData&& PreparedStatement . getParameterMetaData()
获得代表PreparedStatement元数据的ParameterMetaData对象。
例如:SQL语句 “ Select * from user where name=? And password=?& ” 中的两个“ ?” 问号。
ParameterMetaData对象 中的方法:
&&&&&&&&(1) getParameterCount()&&&&--获得指定参数的个数
&&&&&&&&(2) getParameterType(int param)&&&&--&获得指定参数的sql类型(Mysql数据库不支持该方法,会报异常。)
Demo样例:参数元数据
&&&&&&public&void&test2()&throws&SQLException{
&&&&&&&&&&&&Connection&conn&=&JdbcUtils_C3P0.getConnection();
&&&&&&&&&&&&String&sql&=&&insert&into&user(id,name)&values(?,?)&;
&&&&&&&&&&&&PreparedStatement&st&=&conn.prepareStatement(sql);
&&&&&&&&&&&&ParameterMetaData&meta&=&st.getParameterMetaData();
&&&&&&&&&&&&System.out.println(meta.getParameterCount());
&&&&&&&&&&&&System.out.println(meta.getParameterType(1));&
3、自定义JDBC框架&——结果集元数据: ResultSetMetaData
ResultSetMetaData&& ResultSet. getMetaData()
获得代表ResultSet对象元数据的ResultSetMetaData对象。
&&&&ResultSetMetaData对象中的方法
&&&&&&&&&&&&(1) getColumnCount()&&&&--&返回resultset对象的列数
&&&&&&&&&&&&(2) getColumnName(int column)&&&&--&获得指定列的名称
&&&&&&&&&&&&(3) getColumnTypeName(int column)&&&&--&获得指定列的类型
Demo样例: 结果集元数据
&&&&&&public&void&test3()&throws&SQLException{
&&&&&&&&&&&&Connection&conn&=&JdbcUtils_C3P0.getConnection();
&&&&&&&&&&&&String&sql&=&&select&*&from&account&;
&&&&&&&&&&&&PreparedStatement&st&=&conn.prepareStatement(sql);
&&&&&&&&&&&&ResultSet&rs&=&st.executeQuery();
&&&&&&&&&&&&ResultSetMetaData&&meta&=&rs.getMetaData();
&&&&&&&&&&&&System.out.println(meta.getColumnCount());
&&&&&&&&&&&&System.out.println(meta.getColumnName(1));
&&&&&&&&&&&&System.out.println(meta.getColumnName(2));
&&&&&&&&&&&&System.out.println(meta.getColumnName(3));&&&&
4、使用元数据简化JDBC代码
业务背景:系统中所有实体对象都涉及到基本的CRUD操作:
&&&&&&&&(1) 万能更新
&&&&&&&&所有实体的CUD操作代码基本相同,仅仅发送给数据库的SQL语句不同而已,因此可以把CUD操作的所有相同代码抽取到工具类的一个update方法中,并定义参数接收变化的SQL语句。
Demo样例1:万能更新的方法内容部分
&&&&public&static&void&update(String&sql,Object&params[])&throws&SQLException{
&&&&&&&&Connection&conn&=&
&&&&&&&&PreparedStatement&st&=&
&&&&&&&&ResultSet&rs&=&
&&&&&&&&try{
&&&&&&&&&&&&&&conn&=&getConnection();
&&&&&&&&&&&&&&st&=&conn.prepareStatement(sql);
&&&&&&&&&&&&&&for(int&i=0;i&params.i++){
&&&&&&&&&&&&&&&&&&&&st.setObject(i+1,params[i]);
&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&st.executeUpdate();
&&&&&&&&}finally{
&&&&&&&&&&&&&&release(conn,&st,&rs);
Demo样例2:万能更新方法的调用代码
&&&&public&class&CustomerDaoImpl&implements&CustomerDao&{&
&&&&&&&&&&public&void&add(Customer&c){
&&&&&&&&&&&&&&&&try{
&&&&&&&&&&&&&&&&&&&&&&String&sql&=&&insert&into&customer(id,name,gender,birthday,cellphone,email,preference,type,description)&values(?,?,?,?,?,?,?,?,?)&;
&&&&&&&&&&&&&&&&&&&&&&Object&params[]&=&{c.getId(),c.getName(),c.getGender(),c.getBirthday(),c.getCellphone(),c.getEmail(),c.getPreference(),c.getType(),c.getDescription()};
&&&&&&&&&&&&&&&&&&&&&&JdbcUtils.update(sql,&params);
&&&&&&&&&&&&&&&&}catch&(Exception&e)&{
&&&&&&&&&&&&&&&&&&&&&&throw&new&DaoException(e);
&&&&&&&&&&&&&&&&}
&&&&&&&&&&}
&&&&&&&&&&public&void&update(Customer&c){&&&//id
&&&&&&&&&&&&&&&&try{
&&&&&&&&&&&&&&&&&&&&&&String&sql&=&&update&customer&set&name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=?&&where&id=?&;
&&&&&&&&&&&&&&&&&&&&&&Object&params[]&=&{c.getName(),c.getGender(),c.getBirthday(),c.getCellphone(),c.getEmail(),c.getPreference(),c.getType(),c.getDescription(),c.getId()};
&&&&&&&&&&&&&&&&&&&&&&JdbcUtils.update(sql,&params);
&&&&&&&&&&&&&&&&}catch&(Exception&e)&{
&&&&&&&&&&&&&&&&&&&&&&throw&new&DaoException(e);
&&&&&&&&&&&&&&&&}&
&&&&&&&&&&}
&&&&&&&&&&public&void&delete(String&id){
&&&&&&&&&&&&&&&&try{
&&&&&&&&&&&&&&&&&&&&&&String&sql&=&&delete&from&customer&where&id=?&;
&&&&&&&&&&&&&&&&&&&&&&Object&params[]&=&{id};
&&&&&&&&&&&&&&&&&&&&&&JdbcUtils.update(sql,&params);
&&&&&&&&&&&&&&&&}catch&(Exception&e)&{
&&&&&&&&&&&&&&&&&&&&&&throw&new&DaoException(e);
&&&&&&&&&&&&&&&&}&
&&&&&&&&&&}&
&&&&&&&&(2)&万能查询
&&&&&&&&实体的R操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet的映射也各不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中。
&&&&&&&&&备注:关于自定义万能查询的代码,涉及到自定义处理器等代码,上面所述的数据库元数据的各种知识也都应用到其中,故有些复杂,不便学习。有万能查询需求的请学习Apache—DBUtils框架 中的查询方法部分,相对来说只要会调用即可,学习成本会小一些。
5、Apache—DBUtils框架简介
&&&&&&&&commons-dbutils&是&Apache&组织提供的一个开源&JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。
&&&&&&&&工具类:&&&&mons.dbutils.DbUtils。&&&
&&&&&&&&API介绍:
&&&&&&&&&&&(1) &mons.dbutils.QueryRunner&
&&&&&&&&&&&(2)& mons.dbutils.ResultSetHandler
6、DbUtils类&介绍
&&&&&&&&DbUtils&:提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
&&&&&&&&(1) public&static&void&close(…)&throws&java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
&&&&&&&&(2) public&static&void&closeQuietly(…):&这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLException。
&&&&&&&&(3) public&static&void&commitAndCloseQuietly(Connection&conn):&用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。&
&&&&&&&&(4) public&static&boolean&loadDriver(java.lang.String&driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
7、QueryRunner类 介绍
&&&&&&&&该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
&&&&&&&&QueryRunner类提供了两个构造方法:
&&&&&&&&&&&&(1) 默认的构造方法:
&&&&&&&&&&&&&&&&&&&&QueryRunner()&
&&&&&&&&&&&&(2) 需要一个&javax.sql.DataSource&来作参数的构造方法。
&&&&&&&&&&&&&&&&&&&&QueryRunner(DataSource&ds)&
8、QueryRunner类的主要方法
&&&&&&&&(1) public&Object&query(Connection&conn,&String&sql,&Object[]&params,&ResultSetHandler&rsh)&throws&SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理&PreparedStatement&和&ResultSet&的创建和关闭。
&&&&&&&&(2) public&Object&query(String&sql,&Object[]&params,&ResultSetHandler&rsh)&throws&SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource)&或使用的setDataSource&方法中重新获得&Connection。&&&&&&&&&
&&&&&&&&(3) public&Object&query(Connection&conn,&String&sql,&ResultSetHandler&rsh)&throws&SQLException&:&执行一个不需要置换参数的查询操作。&&&&&&&&&
&&&&&&&&(4) public&int&update(Connection&conn,&String&sql,&Object[]&params)&throws&SQLException:用来执行一个更新(插入、更新或删除)操作。&&&&&&&&
&&&&&&&&(5) public&int&update(Connection&conn,&String&sql)&throws&SQLException:用来执行一个不需要置换参数的更新操作。
Demo样例:使用dbutils完成数据库的crud&
public&class&Demo1&{&
&&&create&database&day17;
&&&use&day17;
&&&create&table&users(
&&&&id&int&primary&key,
&&&&name&varchar(40),
&&&&password&varchar(40),
&&&&email&varchar(60),
&&&&birthday&date
&&public&void&insert()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&insert&into&users(id,name,password,email,birthday)&values(?,?,?,?,?)&;
&&&&Object&params[]&=&{2,&bbb&,&123&,&&,new&Date()};
&&&&runner.update(sql,&params);
&&public&void&update()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&update&users&set&email=?&where&id=?&;
&&&&Object&params[]&=&{&&,1};
&&&&runner.update(sql,&params);
&&public&void&delete()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&delete&from&users&where&id=?&;
&&&&runner.update(sql,&1);
&&public&void&find()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&*&from&users&where&id=?&;
&&&&User&user&=&(User)&runner.query(sql,&1,&new&BeanHandler(User.class));
&&&&System.out.println(user.getEmail());
&&public&void&getAll()&throws&Exception{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&*&from&users&;
&&&&List&list&=&(List)&runner.query(sql,&new&BeanListHandler(User.class));
&&&&System.out.println(list);
&&public&void&batch()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&&insert&into&users(id,name,password,email,birthday)&values(?,?,?,?,?)&;
&&&&Object&params[][]&=&new&Object[3][5];
&&&&for(int&i=0;i&params.i++){&&//3
&&&&&&params[i]&=&new&Object[]{i+1,&aa&+i,&123&,i&+&&@&,new&Date()};
&&&&runner.batch(sql,&params);
9、ResultSetHandler接口&介绍
&&&&&&&&该接口用于处理&java.sql.ResultSet,将数据按要求转换为另一种形式。
&&&&&&&&ResultSetHandler&接口提供了一个单独的方法:Object&handle&(java.sql.ResultSet&.rs)。
10、ResultSetHandler&接口的实现类
&&&&&&& (1)&ArrayHandler( ):把结果集中的第一行数据转成对象数组。
&&&&&&&&(2) ArrayListHandler( ):把结果集中的每一行数据都转成一个数组,再存放到List中。
&&&&&&&&(3) BeanHandler(Class&type)&:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
&&&&&&&&(4) BeanListHandler(Class&type)&:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
&&&&&&&&(5) ColumnListHandler(int&columnIndex&/&String&columnName):将结果集中某一列的数据存放到List中。
&&&&&& &(6)&KeyedHandler( int&columnIndex&/&String&columnName ):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,并将其columnName的值作为指定的key。
&&&&&&& (7)&MapHandler( ):将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
&&&&&&&&(8) MapListHandler( ):将结果集中的每一行数据都封装到一个Map里,然后再存放到List
&&&&&& &(9)&&ScalarHandler( ):将结果集中的某一列&装入到一个对象中。
Demo样例:测试dbutils的各个结果集处理器
public&class&Demo2&{&&&
&&public&void&test1()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&*&from&users&where&id=?&;
&&&&Object&result[]&=&(Object[])&runner.query(sql,1,&new&ArrayHandler());
&&&&System.out.println(result[0]);
&&&&System.out.println(result[1]);
&&public&void&test2()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&*&from&users&;
&&&&List&list&=&(List)&runner.query(sql,&new&ArrayListHandler());
&&&&System.out.println(list);
&&public&void&test3()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&*&from&users&;
&&&&List&list&=&(List)&runner.query(sql,&new&ColumnListHandler1(&name&));
&&&&System.out.println(list);
&&public&void&test4()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&*&from&users&;
&&&&Map&Integer,Map&String,Object&&&map&=&(Map)&runner.query(sql,&new&KeyedHandler(&id&));
&&&&for(Map.Entry&Integer,Map&String,Object&&&me&:&map.entrySet()){
&&&&&&int&id&=&me.getKey();
&&&&&&for(Map.Entry&String,&Object&&entry&:&me.getValue().entrySet()){
&&&&&&&&String&name&=&entry.getKey();
&&&&&&&&Object&value&=&entry.getValue();
&&&&&&&&System.out.println(name&+&&=&&+&value);
&&@Test&&//获取总记录数。
&&public&void&test5()&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&select&count(*)&from&users&;
&&&&/*&方式一:
&&&&Object&result[]&=&(Object[])&runner.query(sql,&new&ArrayHandler());
&&&&long&totalrecord&=&(Long)result[0];
&&&&int&num&=&(int)
&&&&System.out.println(num);
&&&&int&totalrecord&=&((Long)result[0]).intValue();
&&&&//方式二:
&&&&int&totalrecord&=&((Long)runner.query(sql,&new&ScalarHandler(1))).intValue();
&&&&System.out.println(totalrecord);
class&ColumnListHandler1&implements&ResultSetHandler{&
&&private&String&columnN
&&public&ColumnListHandler1(String&columnName){
&&&&this.columnName&=&columnN
&&public&Object&handle(ResultSet&rs)&throws&SQLException&{
&&&&List&list&=&new&ArrayList();
&&&&while(rs.next()){
&&&&&&list.add(rs.getObject(columnName));
&&&&return&
11、JDBC应用的事务管理(ThreadLocal类)&
JDBC&应用的事务管理——Service层和Dao层事务的传递。
&&&&方式一:跨层传递方法参数——在Service层创建开启事务的连接,并传递到Dao层,最后在Service层提交事务;
&&&&方式二:ThreadLocal 绑定连接——使用ThreadLocal进行事务管理——ThreadLocal可以实现在线程范围内实现数据共享。
&&&&&方式三:使用Spring进行事务管理;(在Spring 博文中讲解。)
&&&&&&&&&&&&&&&&&&&&
12、JDBC应用的事务管理——采用跨层跨层传递方法参数
思想:在Service层创建开启事务的连接,并传递到Dao层,最后在Service层提交事务;
Demo样例1:Service层(Dao层中只要在方法中参数中接收该 连接参数 就好了)
public&class&BusinessService&{&&
&&create&table&account(
&&&&id&int&primary&key&auto_increment,
&&&&name&varchar(40),
&&&&money&float
&&)character&set&utf8&collate&utf8_general_
&&insert&into&account(name,money)&values('aaa',1000);
&&insert&into&account(name,money)&values('bbb',1000);
&&insert&into&account(name,money)&values('ccc',1000);&
&&public&void&transfer1(int&sourceid,int&targetid,double&money)&throws&SQLException{
&&&&Connection&conn&=&
&&&&&&//&获取连接并开启事务。
&&&&&&conn&=&JdbcUtils.getConnection();
&&&&&&conn.setAutoCommit(false);
&&&&&&//&将开启事务的连接传递到各层。
&&&&&&AccountDao&dao&=&new&AccountDao(conn);
&&&&&&Account&a&=&dao.find(sourceid);&&&//select
&&&&&&Account&b&=&dao.find(targetid);&&&//select
&&&&&&a.setMoney(a.getMoney()-money);&&
&&&&&&b.setMoney(b.getMoney()+money);&&&
&&&&&&dao.update(a);&//update&&&&&&
&&&&&&dao.update(b);//update
&&&&&&//&提交事务。
&&&&&&mit();
&&&&}finally{
&&&&&&//&关闭连接。
&&&&&&if(conn!=null)&conn.close();
13、JDBC应用的事务管理—— ThreadLocal 绑定连接
思想:在Service层将开启事务的连接绑定到ThreadLocal中,在当前线程所途径的其他各层从ThreadLocal中获取连接并进行操作,最后线程返回至Service层时,再提交事务,移除绑定的链接。
Demo样例1:将 使用ThreadLocal 绑定连接 的代码封装成工具类。
public&class&JdbcUtils&{
&&private&static&DataSource&
&&//&为保证各层的类所使用的ThreadLocal是同一个,建议将其设定成静态的,但是一定要记得使用后要移出绑定在上面的对象。
&&private&static&ThreadLocal&Connection&&tl&=&new&ThreadLocal&Connection&();&&// 其实就是一个Map集合
&&&&&&Properties&prop&=&new&Properties();
&&&&&&InputStream&in&=&JdbcUtils.class.getClassLoader().getResourceAsStream(&dbcpconfig.properties&);
&&&&&&prop.load(in);
&&&&&&BasicDataSourceFactory&factory&=&new&BasicDataSourceFactory();
&&&&&&ds&=&factory.createDataSource(prop);
&&&&}catch&(Exception&e)&{
&&&&&&throw&new&ExceptionInInitializerError(e);
&&public&static&DataSource&getDataSource(){
&&&&return&
&&//&备注:该获取连接的方法,仅当使用ThreadLocal来管理事务连接的情况,因为向静态对象ThreadLocal中绑定了对象,所以当我们不需要管理事务的普通获取连接的方法,就不要用此方法。应该用普通的获取连接的方法。
&&public&static&Connection&getConnection()&throws&SQLException{
&&&&&&//得到当前线程上绑定的连接
&&&&&&Connection&conn&=&tl.get();
&&&&&&if(conn==null){&&//代表线程上没有绑定连接
&&&&&&&&conn&=&ds.getConnection();
&&&&&&&&tl.set(conn);
&&&&&&return&
&&&&}catch&(Exception&e)&{
&&&&&&throw&new&RuntimeException(e);
&&public&static&void&startTransaction(){
&&&&&&//得到当前线程上绑定连接开启事务
&&&&&&Connection&conn&=&tl.get();
&&&&&&if(conn==null){&&//代表线程上没有绑定连接
&&&&&&&&conn&=&ds.getConnection();
&&&&&&&&tl.set(conn);
&&&&&&conn.setAutoCommit(false);
&&&&}catch&(Exception&e)&{
&&&&&&throw&new&RuntimeException(e);
&&public&static&void&commitTransaction(){
&&&&&&Connection&conn&=&tl.get();
&&&&&&if(conn!=null){
&&&&&&&&mit();
&&&&}catch&(Exception&e)&{
&&&&&&throw&new&RuntimeException(e);
&&public&static&void&closeConnection(){
&&&&&&Connection&conn&=&tl.get();
&&&&&&if(conn!=null){
&&&&&&&&conn.close();
&&&&}catch&(Exception&e)&{
&&&&&&throw&new&RuntimeException(e);
&&&&}finally{
&&&&&&tl.remove();&&&//千万注意,解除当前线程上绑定的链接(从threadlocal容器中移除对应当前线程的链接)
Demo样例2: 采用 ThreadLocal 绑定连接 来管理事务的 Service层的代码。
public&class&BusinessService&{&&
&&create&table&account(
&&&&id&int&primary&key&auto_increment,
&&&&name&varchar(40),
&&&&money&float
&&)character&set&utf8&collate&utf8_general_
&&insert&into&account(name,money)&values('aaa',1000);
&&insert&into&account(name,money)&values('bbb',1000);
&&insert&into&account(name,money)&values('ccc',1000);&
&&//用上ThreadLocal的事务管理
&&public&void&transfer2(int&sourceid,int&targetid,double&money)&throws&SQLException{
&&&&&&JdbcUtils.startTransaction();
&&&&&&AccountDao&dao&=&new&AccountDao();
&&&&&&Account&a&=&dao.find(sourceid);&&&//select
&&&&&&Account&b&=&dao.find(targetid);&&&//select
&&&&&&a.setMoney(a.getMoney()-money);&&
&&&&&&b.setMoney(b.getMoney()+money);&&&
&&&&&&dao.update(a);&//update
&&&&&&dao.update(b);//update
&&&&&&mitTransaction();
&&&&}finally{
&&&&&&JdbcUtils.closeConnection();
14、使用JDBC操作多个表
&&&&&&&&(1) 使用JDBC操作多表的步骤
&&&&&&&&&&&&&&&&(a)&&明确对象的属性,及之间的关联关系。
&&&&&&&&&&&&&&&&(b)&&明确表关系,&创建数据库及表;
&&&&&&&&&&&&&&&&(c)& 编码Dao层的代码(重点是增删改查时涉及到的级联操作。)
&&&&&&&&&&&&&&&&(d)& 编码Service层的代码(重点是 复杂对象& 的级联操作。)
&&&&&&&&(2)& O-R Mapping 映射的注意事项
&&&&&&&&&&&&&&&&(a) 不管java的对象存在何种关系,反映到关系型数据库中,都是使用外键表示纪录(即对象)的关联关系。
&&&&&&&&&&&&&&&&(b) 设计java对象如涉及到多个对象相互引用,要尽量避免使用一对多,或多对多关系,而应使用多对一描述对象之间的关系(或使用延迟加载的方式)。以避免查询出了所有“一对多”中&“多”的数据,容易造成内存溢出
&&&&&&&&&&&&&&&&(c) 特殊情况下(比如订单--订单项)必须设计成“一对多”关系时,当“多”的一方数据较少时,可以使用级联查询,但若是“多”的一方数据量较大时,则建议使用&“分页方式”查询。&
&&&&&&&&&(3) &“一对多”多表关联关系的设计方法:
&&&&&&&&&&&&&&&&(a) 先将每张表各自的基本属性信息列好;
&&&&&&&&&&&&&&&&(b) 再将“一对多”&多的一方中设定外键列(并添加外键约束,以维护两表之间的关系)。
&&&&&&&&(4) 常用O-R&Mapping映射工具
&&&&&&&&&&&&&&&&(a) Hibernate
&&&&&&&&&&&&&& &(b)&Ibatis
&&&&&&&&&&&&&&&&(c) Commons&DbUtils(只是对JDBC简单封装)
15、使用JDBC操作多个表—— 一对多关系 (例如:部门和员工)
Demo样例1:Dao层的代码
public&class&DepartmentDao&{&
&&&&多表设计原则
&&&&1、现将各表各自的基本属性信息列好;
&&&&2、再将“一对多”&多的一方中设定外键列(并添加外键约束,以维护两表之间的关系)。
&&&&create&table&department
&&&&&&id&varchar(40)&primary&key,
&&&&&&name&varchar(40)
&&&&create&table&employee
&&&&&&id&varchar(40)&primary&key,
&&&&&&name&varchar(40),
&&&&&&salary&double,
&&&&&&department_id&varchar(40),
&&&&&&constraint&department_id_FK&foreign&key(department_id)&references&department(id)
&&&&alter&table&employee&drop&foreign&key&department_id_FK;
&&&&alter&table&employee&add&constraint&department_id_FK&foreign&key(department_id)&references&department(id)&on&delete&set&
&&&&alter&table&employee&drop&foreign&key&department_id_FK;
&&&&alter&table&employee&add&constraint&department_id_FK&foreign&key(department_id)&references&department(id)&on&delete&&
&&public&void&add(Department&d)&throws&SQLException{&
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&//1.把department对象的数据插入到department表
&&&&String&sql&=&&insert&into&department(id,name)&values(?,?)&;
&&&&Object&params[]&=&{d.getId(),d.getName()};
&&&&runner.update(sql,&params);
&&&&//2.把department对象中维护的所有员工插入到员工表
&&&&Set&Employee&&set&=&d.getEmployees();
&&&&for(Employee&e&:&set){
&&&&&&sql&=&&insert&into&employee(id,name,salary,department_id)&values(?,?,?,?)&;
&&&&&&params&=&new&Object[]{e.getId(),e.getName(),e.getSalary(),d.getId()};
&&&&&&runner.update(sql,&params);
&&&&//3.更新员工表的外键列,说明员工的部门(本例中的ID可以实现给定,固就不需要进行更新外键列操作;但若是涉及到获取 自动生成主键 的案例时,则需要 涉及到更新外键操作)。
&&//该方法查询出了所有“一对多”中&“多”的数据,容易造成内存溢出。当“多”的一方数据较少时,可以使用该级联查询,但若是“多”的一方数据量较大时,则建议使用&“分页方式”查询。
&&public&Department&find(String&id)&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&//1.找部门表,查出部门的基本信息
&&&&String&sql&=&&select&*&from&department&where&id=?&;
&&&&Department&d&=&(Department)&runner.query(sql,&id,&new&BeanHandler(Department.class));
&&&&//2.找员工表,找出部门下面所有员工
&&&&sql&=&&select&*&from&employee&where&department_id=?&;
&&&&List&list&=&(List)&runner.query(sql,&id,&new&BeanListHandler(Employee.class));
&&&&d.getEmployees().addAll(list);&&&&// 注:set集合的addAll() 是将所有的值逐个取出来,再逐一存入到Set集合中;而set集合的add()方法则是替换一Set集合的引用。
&&&&return&d;
&&public&void&delete(String&id)&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql=&&delete&from&department&where&id=?&;
&&&&runner.update(sql,&id);
Demo样例2:Service层的代码&
public&class&BService&{&
&&public&void&add()&throws&SQLException{&
&&&&Department&d&=&new&Department();
&&&&d.setId(&111&);
&&&&d.setName(&开发部&);
&&&&Employee&e1&=&new&Employee();
&&&&e1.setId(&1&);
&&&&e1.setName(&aa&);
&&&&e1.setSalary(10000);&
&&&&Employee&e2&=&new&Employee();
&&&&e2.setId(&2&);
&&&&e2.setName(&bb&);
&&&&e2.setSalary(10000);
&&&&d.getEmployees().add(e1);
&&&&d.getEmployees().add(e2);&
&&&&DepartmentDao&dao&=&new&DepartmentDao();
&&&&dao.add(d);
&&public&void&find()&throws&SQLException{
&&&&DepartmentDao&dao&=&new&DepartmentDao();
&&&&Department&d&=&dao.find(&111&);
&&&&System.out.println(d);
&&public&void&delete()&throws&SQLException{
&&&&DepartmentDao&dao&=&new&DepartmentDao();
&&&&dao.delete(&111&);
16、使用JDBC操作多个表—— 多对多关系 (老师和学生)
Demo样例1:Dao层的代码
public&class&TeacherDao&{&
&&create&table&teacher
&&&&id&varchar(40)&primary&key,
&&&&name&varchar(40),
&&&&salary&double
&&create&table&student
&&&&id&varchar(40)&primary&key,
&&&&name&varchar(40)
&&&create&table&teacher_student
&&&&&teacher_id&varchar(40),
&&&&&student_id&varchar(40),
&&&&&primary&key(teacher_id,student_id),
&&&&&constraint&teacher_id_FK&foreign&key(teacher_id)&references&teacher(id),&
&&&&&constraint&student_id_FK&foreign&key(student_id)&references&student(id)
&&&alter&table&teacher_student&drop&foreign&key&teacher_id_FK;
&&&alter&table&teacher_student&add&constraint&teacher_id_FK&foreign&key(teacher_id)&references&teacher(id)&on&delete&&&
&&&alter&table&teacher_student&drop&foreign&key&student_id_FK;
&&&alter&table&teacher_student&add&constraint&student_id_FK&foreign&key(student_id)&references&student(id)&on&delete&
&&public&void&add(Teacher&t)&throws&SQLException&{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&//1`.取出老师存老师表
&&&&String&sql&=&&insert&into&teacher(id,name,salary)&values(?,?,?)&;
&&&&Object&params[]&=&{t.getId(),t.getName(),t.getSalary()};
&&&&runner.update(sql,&params);
&&&&//2.取出老师所有学生的数据,存学生表
&&&&Set&Student&&set&=&t.getStudents();
&&&&for(Student&s&:&set){
&&&&&&sql&=&&insert&into&student(id,name)&values(?,?)&;
&&&&&&params&=&new&Object[]{s.getId(),s.getName()};
&&&&&&runner.update(sql,&params);
&&&&&&//3.更新中间表,说明老师和学生的关系
&&&&&&sql&=&&insert&into&teacher_student(teacher_id,student_id)&values(?,?)&;
&&&&&&params&=&new&Object[]{t.getId(),s.getId()};
&&&&&&runner.update(sql,&params);
&&public&Teacher&find(String&id)&throws&SQLException{
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&//1.找老师表,找出老师的基本信息
&&&&String&sql&=&&select&*&from&teacher&where&id=?&;
&&&&Teacher&t&=&(Teacher)&runner.query(sql,&id,&new&BeanHandler(Teacher.class));
&&&&//2.找出老师的所有学生&&&&()
&&&&//sql&=&&select&s.*&from&teacher_student&ts,student&s&where&ts.teacher_id=?&and&ts.student_id=s.id&;
&&&&sql&=&&select&s.*&from&teacher_student&ts,student&s&where&ts.teacher_id=?&and&ts.student_id=s.id&;
&&&&List&list&=&(List)&runner.query(sql,&id,&new&BeanListHandler(Student.class));
&&&&t.getStudents().addAll(list);
&&&&return&t;
&&public&void&delete(String&id){
&&&&QueryRunner&runner&=&new&QueryRunner(JdbcUtils.getDataSource());
&&&&String&sql&=&&delete&from&teacher&where&id=?&;
Demo样例2:Service层的代码&
public&class&BService&{
&public&void&addTeacher()&throws&SQLException{
&&Teacher&t&=&new&Teacher();
&&t.setId(&1&);
&&t.setName(&老张&);
&&t.setSalary(100000);
&&Student&s1&=&new&Student();
&&s1.setId(&1&);
&&s1.setName(&aa&);
&&Student&s2&=&new&Student();
&&s2.setId(&2&);
&&s2.setName(&bb&);
&&t.getStudents().add(s1);
&&t.getStudents().add(s2);&
&&TeacherDao&dao&=&new&TeacherDao();
&&dao.add(t);
&public&void&findTeacher()&throws&SQLException{
&&TeacherDao&dao&=&new&TeacherDao();
&&Teacher&t&=&dao.find(&1&);
&&System.out.println(t);
17、数据库端——表关系间的级联操作
表关系间的级联操作:
&&&&REFERENCES&tbl_name&[(index_col_name,...)]
&&&&&&&&&&&&&&&[MATCH&FULL&|&MATCH&PARTIAL&|&MATCH&SIMPLE]
&&&&&&&&&&&&&&&[ON&DELETE&reference_option]&&(级联删除)&&
&&&&&&&&&&&&&&&[ON&UPDATE&reference_option]&&(级联修改)
reference_option的可选值:
&&&&RESTRICT&|&CASCADE(删除)&|&SET&NULL(置空)&|&NO&ACTION&
Demo:给表添加外键约束——包含级联删除(置空)的关系
&& alter&table&employee&add&constraint&department_id_FK&foreign&key(department_id)&references&department(id)&on&delete&set&null&;&
&&&alter&table&employee&add&constraint&department_id_FK&foreign&key(department_id)&references&department(id)&on&delete&set&
&&&&alter&table&employee&add&constraint&department_id_FK&foreign&key(department_id)&references&department(id)&on&delete&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:64113次
积分:1469
积分:1469
排名:第19533名
原创:65篇
转载:121篇
(3)(3)(8)(17)(1)(2)(2)(11)(3)(4)(20)(5)(2)(9)(10)(9)(3)(1)(5)(5)(3)(3)(1)(4)(8)(6)(5)(16)(11)(9)

我要回帖

更多关于 resultsethandler t 的文章

 

随机推荐