`

day15 JDBC元数据 DBUtils 开发模型

 
阅读更多

人们直接使用JDBC开发,非常麻烦 ----- 企业中开发web程序,连接数据库 通过JDBC框架
1、JDBC元数据API (编写JDBC框架基础)
2、编写自己JDBC框架(重点理解框架编写思想,代码不做要求)
3、Apache DBUtils 框架

什么是数据库元数据(MetaData):数据库存储结构定义信息 (库、表、列 定义信息)
学习元数据API 获得 数据库、表、列定义信息

1、DatabaseMetaData 数据库元数据 ----- 获得数据库结构信息
新建web工程
将mysql驱动 c3p0的jar包 复制WEB-INF/lib
将c3p0-config.xml 复制 src目录下 (修改数据库连接参数)
编写JDBCUtils (用c3p0连接池获得一个连接)

create table users(
  id int primary key not null auto_increment,
  username varchar(40) unique not null,
  password varchar(40) not null,
  email varchar(100)
);

insert into users values(null,'zs','123','zs@itcast.cn');
insert into users values(null,'lisi','123456','lisi@itcast.cn');
insert into users values(null,'wu','123','wangwu@itcast.cn');

* 获得JDBC连接参数 、获得主键、外键信息 、获得数据表、获得数据列信息

2、ParameterMetaData 参数元数据 ---- 获得预编译SQL语句中 ? 信息
getParameterCount()  参数个数 ---- ? 个数
getParameterType(int param)  ----- 参数类型
getParameterTypeName(int param)  --- 参数类型名称

获得类型时:
java.sql.SQLException: Parameter metadata not available for the given statement

3、ResultSetMetaData 结果集元数据 ---- 获得结果集列名称、数量、类型
getColumnCount() 返回resultset对象的列数
getColumnName(int column)  获得指定列的名称
getColumnTypeName(int column) 获得指定列的类型

* 学习JDBC元数据API ---- 编写通用JDBC程序(JDBC框架)
构造bean
 @Test
 public void testmeta() throws SQLException {
  PreparedStatement pre = JDBUtils.getConnection().prepareStatement(
    "select * from nc_info limit 0,1");
  ResultSetMetaData meta = pre.getMetaData();
  for (int i = 1; i <= meta.getColumnCount(); i++) {
   if (meta.getColumnTypeName(i).equalsIgnoreCase("INT")) {
    System.out
      .println("int " + meta.getColumnName(i).toLowerCase());
   }
   if (meta.getColumnTypeName(i).equalsIgnoreCase("varchar")) {
    System.out.println("String "
      + meta.getColumnName(i).toLowerCase()+";");
   }
  }
 }

------------------------------------------------------------------------------------
每次编写JDBC程序都发现存在好多重复代码 ---- 通过通用程序进行简化
1、通过CUD方法设计
create table account(
  id int primary key not null auto_increment,
  name varchar(40),
  money double
);
insert into account values(null,'aaa',1000);
insert into account values(null,'bbb',1000);
insert into account values(null,'ccc',1000);

为两张表 编写DAO程序 insert 方法(update方法和delete方法 和插入方法类似)

public static void update(String sql, Object... args) {} ---- 参数传入SQL 和 SQL中?对应数据

2、通用R方法设计
public static Object query(String sql, MyResultSetHandler handler,Object... args) {}


Apache DBUtils (轻量级) ---- 使用方便
只是对JDBC程序进行简单封装,从而简化开发者 创建连接、结果集封装、释放资源

QueryRunner 是DBUtils 核心操作类
ResultSetHandler 结果集封装处理器
DbUtils 工具类

DbUtils 工具类 : 加载驱动、关闭、事务提交、回滚

QueryRunner
QueryRunner()  ---- 空参数构造器
QueryRunner(DataSource ds)  --- 接收数据库连接池构造器

batch(Connection conn, String sql, Object[][] params)  ---- 传递连接批处理
batch(String sql, Object[][] params)  ---- 不传递连接批处理

query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
query(String sql, ResultSetHandler<T> rsh, Object... params)

update(Connection conn, String sql, Object... params)
update(String sql, Object... params)

1、如果使用 QueryRunner(DataSource ds) 构造QueryRunner 对象,数据库事务交给DBUtils框架进行管理 ---- 默认情况下每条sql 单独一个事务
batch(String sql, Object[][] params)
query(String sql, ResultSetHandler<T> rsh, Object... params)
update(String sql, Object... params)

2、如果使用 QueryRunner() 构造QueryRunner , 需要自己管理事务,因为框架没有连接池无法获得数据库连接
batch(Connection conn, String sql, Object[][] params)
query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
update(Connection conn, String sql, Object... params)

学习QueryRunner 通用insert 、update 、delete操作方法 -----  update(String sql, Object... params)
* sql中?顺序、数量和可变参数params 对应

 // 事务控制
 @Test
 public void testTransfer() throws SQLException {
  double money = 100;
  String outAccount = "aaa";
  String inAccount = "bbb";
  String sql1 = "update account set money = money - ? where name= ?";
  String sql2 = "update account set money = money + ? where name= ?";

  // QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  // 默认每条sql 一个单独事务

  QueryRunner queryRunner = new QueryRunner();// 不要传递连接池 --- 手动事务管理
  Connection conn = JDBCUtils.getConnection();
  conn.setAutoCommit(false);
  try {
   queryRunner.update(conn, sql1, money, outAccount);
   // int d = 1 / 0;
   queryRunner.update(conn, sql2, money, inAccount);

   System.out.println("事务提交!");
   DbUtils.commitAndCloseQuietly(conn);
  } catch (Exception e) {
   System.out.println("事务回滚!");
   DbUtils.rollbackAndCloseQuietly(conn);
   e.printStackTrace();
  }
 }

 @Test
 public void testDelete() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "delete from users where id = ?";
  queryRunner.update(sql, 3);
 }

 @Test
 public void testUpdate() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "update users set password = ? where username = ?";
  Object[] param = { "nihao", "小明" };
  queryRunner.update(sql, param);
 }

 @Test
 public void testInsert() throws SQLException {
  // 第一步 创建QueryRunner对象
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());

  // 第二步 准备方法参数
  String sql = "insert into users values(null,?,?,?)";
  Object[] param = { "小丽", "qwe", "xiaoli@itcast.cn" };

  // 第三步 调用 query / update
  queryRunner.update(sql, param);
 }

学习query方法 完整数据表查询 ----- 需要将ResultSet 结果集 封装为一个对象
* 在DBUtils框架中 提供 九个ResultSetHandler 实现类
* 如果想将结果集封装为一个指定的对象,可以直接使用九个实现类

九个默认Handler : ArrayHander 、ArrayListHandler 、BeanHander、BeanListHandler、ColumnListHandler、MapHandler、MapListHandler、KeyedHander、ScalarHandler
* 最常用 BeanHander、BeanListHandler、ColumnListHandler、ScalarHandler


// ScalarHandler 通过保存只有一行一列 结果数据 ---- 分组函数
 @Test
 public void demo9() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select count(*) from account";

  long count = (Long) queryRunner.query(sql, new ScalarHandler(1));
  System.out.println(count);
 }

 // KeyedHandler 将结果集每一行数据 保存map , 将map保存另一个map , key 指定列
 @Test
 public void demo8() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";

  Map<Object, Map<String, Object>> map = queryRunner.query(sql,
    new KeyedHandler("id"));
  System.out.println(map);
 }

 // MapListHandler 将结果集每一行数据 保存map中,key列名 value数据 ---- 在讲map对象保存List集合
 @Test
 public void demo7() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";
  List<Map<String, Object>> list = queryRunner.query(sql,
    new MapListHandler());
  for (Map<String, Object> map : list) {
   System.out.println(map);
  }
 }

 // MapHander 将结果集第一行数据 封装Map集合,key是列名 value第一行数据
 @Test
 public void demo6() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";
  Map<String, Object> map = queryRunner.query(sql, new MapHandler());
  System.out.println(map);
 }

 // ColumnListHandler 作用获得结果集的某一列
 @Test
 public void demo5() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";

  // 因为每列类型 都不一样
  // List<Object> list = queryRunner.query(sql,
  // new ColumnListHandler("name"));
  List<Object> list = queryRunner.query(sql, new ColumnListHandler(2));
  System.out.println(list);
 }

 // BeanListHander 结果集每一条数据 ---JavaBean对象 再保存list集合
 @Test
 public void demo4() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";
  List<Account> accounts = queryRunner.query(sql,
    new BeanListHandler<Account>(Account.class));

  for (Account account : accounts) {
   System.out.println(account.getId());
   System.out.println(account.getName());
   System.out.println(account.getMoney());
   System.out.println("----------------");
  }
 }

 // BeanHandler 将结果集第一行数据 封装 JavaBean对象中
 @Test
 public void demo3() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";

  // 传入 Account.class 为了在方法中 通过反射构造Account对象
  // 使用BeanHandler 注意事项 :表列名 与 类中属性名称一致
  Account account = queryRunner.query(sql, new BeanHandler<Account>(
    Account.class));
  System.out.println(account.getId());
  System.out.println(account.getName());
  System.out.println(account.getMoney());
 }

 // ArrayListHandler 结果集每一行数据保存Object[] ----- List
 @Test
 public void demo2() throws SQLException {
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";
  List<Object[]> list = queryRunner.query(sql, new ArrayListHandler());

  for (Object[] objects : list) {
   System.out.println(Arrays.toString(objects));
  }
 }

 // ArrayHandler 将结果集 第一行数据 存入Object[]
 @Test
 public void demo1() throws SQLException {
  // 使用DBUtils
  QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
  String sql = "select * from account";

  // 数组每一个元素,第一行数据每一列
  Object[] values = queryRunner.query(sql, new ArrayHandler());
  System.out.println(Arrays.toString(values));
 }

--------------------------------------------------------------------------------------------------
客户信息增删改查系统

软件工程开发流程:1、瀑布模型 2、螺旋模型

RUP (Rational Unified Process,统一软件开发过程 ) 采用瀑布模型: 需求 --- 需求分析 --- 系统设计(概要、详细设计)---- 编码 --- 测试 --- 实施 --- 维护
* 瀑布模型 缺陷在编码结束之前,客户看不到最终软件产品 ,如果需求、设计出现明显错漏,导致软件后期无法维护,存在重大缺陷
* 瀑布模型对于 新型软件,需求不定软件 风险较大

敏捷开发理念:迭代开发模式 ,将系统功能分成若干批次 ,对每部分功能实施瀑布模型流程 ,系统随时看到开发结果,始终存在可用软件产品
* 增量开发 ,中途发现设计错误,很容易调整

1、需求 客户信息增删改查
2、系统设计
数据库设计 E-R图

创建数据库 create database customersystem;
* 每个软件都会为数据库创建单独用户并授权

创建用户:create user flower identified by 'flower';
授权:grant all on customersystem.* to flower;

创建数据表
create table customer (
   id varchar(40) primary key not null,
   name varchar(20) unique not null,
   gender varchar(10) not null,
   birthday date not null,
   cellphone varchar(20) not null,
   email varchar(40) unique not null,
   preference varchar(100),
   type varchar(40),
   description varchar(255)
);

----------------------------------------------------
启动navicat lite ---- 创建Connection(name随意写,填写用户名、密码)
双击打开连接
在连接上右键点击 new Database --- 创建数据库 customersystem
双击数据库 开发数据库
在数据库/Table右键 new Table ---- 创建数据表 customer

在工具上方点击manager users --- Add User 创建 flower用户
点击用户展开后 具体数据库 ---- select All 为用户flower 授予 customersystem 所有权限

----------------------------------------------------
系统功能设计
1) 技术选型 mysql + Servlet + JSP + EL +JSTL + BeanUtils + c3p0 + DBUtils
2) 搭建工程环境
创建customermanager 工程 ,将jar包复制 WEB-INF/lib
准备c3p0配置文件
3) 创建package 结构 (javaee三层结构)
cn.itcast.customer.web
cn.itcast.customer.service
cn.itcast.customer.dao
cn.itcast.customer.domain
cn.itcast.customer.utils

使用c3p0、DBUtils ---- 需要工具类
实体类 Customer

4) 发布客户管理系统 ----- 虚拟主机方式
配置tomcat/conf/server.xml 添加虚拟主机 www.customer.com  ---- 路径指向工程根目录
<Host name="www.customer.com"  appBase="D:\work\myclipse\work20120605\customermanager" ...>
修改本地hosts文件 添加域名解析  ---- 127.0.0.1   www.customer.com
将工程下发WebRoot 配置缺省虚拟目录 <Context path="" docBase="WebRoot" />

5) 设计 增加、查询、删除、修改 四个功能 --- UML Unified Modeling Language (UML)又称统一建模语言或标准建模语言
绘制UML工具 很多:Rantional Rose、Microsoft Visio、starUML 、jude(纯java开发)
* UML 做软件 建模(分析设计) : 用例图、类图、时序图


总结:
JDBC元数据API(框架开发基础) ------- 自定义JDBC框架(不要求掌握、理解框架编写过程) ------- Apache DBUtils
* DBUtils 增删改查 、事务处理

三层结构编写java项目
1、客户端:请求是否需要数据 (form / 链接) ---- 提交数据 form action 、 a href
2、web层:获得客户端提交数据,封装JavaBean --- 传递业务层 (BeanUtils)
3、业务层获得客户端数据后,编写程序业务逻辑,如果需要对数据库增删改查 --- 调用DAO
4、DAO 对表增删改查 (DBUtils/C3P0)
5、业务层处理数据结果返回web层 ---- web层根据结果,传递结果数据给JSP显示 ---- request.setAttribute request.getRequestDispatcher.forward

完成客户信息增加、查询

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics