1、什么是数据库
数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。
2、什么是数据库管理系统
数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中表内的数据。
3、数据库表
数据库中以表为组织单位存储数据。
表类似我们的Java类,每个字段都有对应的数据类型。
那么用我们熟悉的java程序来与关系型数据对比,就会发现以下对应关系。
类—–对应—–表
类中属性—–对应—–表中字段
一个对象—-对应——一条记录

4、SQL语法
SQL语句可以单行或多行书写,以分号结尾
MySQL数据库的SQL语句不区分大小写,建议使用大写,例如:SELECT * FROM user。

4.1 创建表

-- 创建表结构
CREATE TABLE users(uid INT PRIMARY KEY AUTO_INCREMENT,uname VARCHAR(20),uaddress VARCHAR(200)
);
-- 查看数据库
SHOW DATABASES;
-- 删除表
DROP TABLE users;
-- 查看数据库中的表
SHOW TABLES;
-- 查看表结构
DESC users;/*
添加列,添加字段
ALTER TABLE users ADD tel INT;
*/DESC users;/*
修改列,在原有的列上修改
修改列名,数据类型约束
ALTER TABLE users MODIFY tel VARCHAR(50)
*/
/*
修改列名
ALTER TABLE users CHANGE tel newtel DOUBLE;
*/
/*
删除列
ALTER TABLE users DROP newtel;
*/

4.2 插入数据

CREATE DATABASE mybase;
SHOW DATABASES;
CREATE TABLE product(-- 主键列,自动增长id INT PRIMARY KEY AUTO_INCREMENT,-- 商品名字,可变字符,非空pname VARCHAR(100) NOT NULL,-- 商品的价格,doubleprice DOUBLE
);
INSERT INTO product (id,sname) VALUES (1,'记事本')
/*
添加数据格式,不考虑主键
格式:
insert into 表名 (列名) values (值)
*/
INSERT INTO product (pname,price) VALUES ('洗衣机',12.01);
/*
添加数据格式,所有值全给出
格式:
insert into 表名 values (全列值)
*/
INSERT INTO product VALUES (2,'微波炉',300.25);
/*
添加数据格式,批量写入
格式:
insert into 表名 (列名1,列名2,列名3) values
(值1,值2,值3),(值1,值2,值3),(值1,值2,值3)
*/
INSERT INTO product(pname,price) VALUES('智能机器人',2599.98),
('沙发',599.98);

4.3 修改表中的数据

/*
对数据进行更新操作
数据在原有的基础上修改
格式:
update 表名 set 列1=值1,列2=值2 where 条件
where 条件:数据中的唯一性
*/
-- 修改智能机器人,价格上调到69999
UPDATE product SET price=69999 WHERE id=3-- 修改沙发,名字改为冰箱,价格改为3222
UPDATE product SET pname='冰箱',price=3222 WHERE id=4
/*
修改条件的写法:
id=6
id<>6  id不等于6
id<=6
&&--->and
||--->or
!---> not
id in (1,2,3,4,5)
id not in (1,2,3,4)
*/
-- 将洗衣机和微波炉的价格都改为666
UPDATE product SET price=666.33 WHERE id=1 OR id=2

4.4 对表中的数据查询

/*
查询指定列数据
格式:select 列名1,列名2 from 表名
*/
SELECT zname,zmoney FROM zhangwu;
/*
查询所有列的数据
格式:select * from 表名
*/
SELECT * FROM zhangwu;
/*
查询去掉重复记录
distinct 关键字 跟随列名
*/
SELECT DISTINCT zname FROM zhangwu;
/*
查询重新命名列
as 关键字
*/
SELECT zname AS '名称' FROM zhangwu;
/*
查询数据中,直接进行数学运算
格式:列对数字进行计算
*/
SELECT zname,zmoney+50 AS 'sum' FROM zhangwu;-- 查询所有的吃饭支出
SELECT * FROM zhangwu WHERE zname='吃饭支出';
-- 查询金额大于240
SELECT * FROM zhangwu WHERE zmoney>200;
-- 查询金额在2000到5000之间
SELECT * FROM zhangwu WHERE zmoney>=200 AND zmoney<=500;
-- 查询金额在2000到5000之间
SELECT * FROM zhangwu WHERE zmoney BETWEEN 200 AND 500;
-- 查询金额是100,200,500其中一个
SELECT * FROM zhangwu WHERE zmoney=100 OR zmoney=200 OR zmoney=500
SELECT * FROM zhangwu WHERE zmoney IN (100,247,500)-- like模糊查询必须配合通配符%(可以表示多个字符,_表示一个字符)
-- 查询所有的支出
SELECT * FROM zhangwu WHERE zname LIKE '%支出'
-- 查询账务名字,五个字符的
SELECT * FROM zhangwu WHERE zname LIKE '_____'
-- 查询账务名不为空的
SELECT * FROM zhangwu WHERE NOT (zname IS NULL);
SELECT * FROM zhangwu WHERE zname IS NOT NULL;

4.4.1 查询排序

/*
查询,对结果集进行排序
升序,降序,对指定列排序order by 列名 [desc][asc]desc 降序asc  升序排列,可以不写
*/
-- 查询账务表,价格进行升序
SELECT * FROM zhangwu ORDER BY zmoney ASC;
-- 查询账务表,价格进行降序
SELECT * FROM zhangwu ORDER BY zmoney DESC;-- 查询账务表,查询所有的支出,对金额降序排序
-- 先过滤条件 where 查询的结果再排序
SELECT * FROM zhangwu WHERE zname LIKE '%支出%' ORDER BY zmoney DESC;

4.4.2 聚合查询

/*
使用聚合函数查询计算,它是对一列数据进行计算*/
-- count 求和,对表中的数据的个数求和 count(列名)
-- 查询统计账务表中,一共有多少条数据
SELECT COUNT(*) AS 'count' FROM zhangwu
-- sum求和,对一列中数据进行求和计算 sum(列名)
-- 对账务表查询,多所有的金额求和计算
SELECT SUM(zmoney) AS 'sum' FROM zhangwu
-- 求和,统计所有支出的总金额,当其中一个为空的话则记为0
SELECT SUM(zmoney) FROM zhangwu WHERE zname LIKE '%收入'
-- max函数,对某列数据获取最大值
SELECT MAX(zmoney) FROM zhangwu

4.4.3 分组查询

/*吃饭支出    共计多少
工资收入    共计多少
服装支出    共计多少
股票收入    共计多少
打麻将支出   共计多少分组查询:group by 分组的列名
必须跟随聚合函数
select 查询的时候,被分组的列,要出现在select选择列的后面
*/
SELECT SUM(zmoney),zname FROM zhangwu GROUP BY zname
-- 对zname内容进行分组查询,但是只要支出并排序
SELECT SUM(zmoney) AS 'getsum',zname FROM zhangwu WHERE zname LIKE '%支出'
GROUP BY zname ORDER BY getsum DESC;
-- 对zname内容进行分组查询求和,但是只要支出,显示金额大于100
-- 结果集分组查询后,再次进行筛选,不能使用where,分组后再次过滤使用关键字having
SELECT SUM(zmoney) AS 'getsum',zname FROM zhangwu WHERE zname LIKE '%支出'
GROUP BY zname HAVING getsum>100
/*
having和where的区别:having是在分组后对数据进行过滤where是在分组前对数据进行过滤having后面可以使用分组函数(统计函数也就是聚合函数)where后面不可以使用分组函数
*/

4.4.4 分页查询

-- 起始位置(要查询第几页-1)乘以第二个参数;第二个参数表示每页显示数目
SELECT * FROM sort LIMIT 6,2;-- 要查询第四页,每页显示两条记录

4.4.5 多表查询

-- 订单表
CREATE TABLE orders(oid VARCHAR(32)PRIMARY KEY,totalprice DOUBLE
);
-- 订单项表
CREATE TABLE orderitem(oid VARCHAR(50),pid VARCHAR(50)
);
-- 添加约束,使得orderitem成为orders和orderitem之间的连接表
ALTER TABLE orderitem ADD CONSTRAINT orderitem_fk FOREIGN KEY(oid)REFERENCES orders(oid);
ALTER TABLE orderitem ADD CONSTRAINT orderitem1_fk FOREIGN KEY(pid)REFERENCES c_product(pid);SELECT * FROM category;
SELECT * FROM c_product;-- 交叉连接,得到的是两个表的乘积
SELECT * FROM category,c_product;
-- 显示内连接(inner可以省略)
SELECT * FROM category INNER JOIN c_product ON cid=category_id;
-- 隐式内连接(内连接查询的是两个表的交集)
SELECT * FROM category c,c_product p WHERE c.cid=p.category_id;
-- 左外连接(查询的是左表的全部以及交集部分)
SELECT * FROM category LEFT JOIN c_product ON cid=category_id;
-- 右外连接(查询的是右表的全部以及交集部分)
SELECT * FROM category RIGHT JOIN c_product ON cid=category_id;-- 子查询(一条select语句结果作为另一条select语法一部分,可以使查询条件、查询结果等)
SELECT * FROM c_product WHERE category_id=(SELECT cid FROM category WHERE cname='化妆品');


4.4.6 主外键约束关系

-- 分类表 主表
CREATE TABLE category(cid VARCHAR(32) PRIMARY KEY,cname VARCHAR(100)
);
-- 商品表 从表
CREATE TABLE c_product(pid VARCHAR(32) PRIMARY KEY,pname VARCHAR(40),price DOUBLE,category_id VARCHAR(32)
);
INSERT INTO category(cid,cname) VALUES('c001','家电');
INSERT INTO category(cid,cname) VALUES('c002','服饰');
INSERT INTO category(cid,cname) VALUES('c003','化妆品');INSERT INTO c_product(pid,pname,price,category_id) VALUES('p001','联想','5000','c001');
INSERT INTO c_product(pid,pname,price,category_id) VALUES('p002','海尔','5000','c001');
INSERT INTO c_product(pid,pname,price,category_id) VALUES('p003','雷神','5000','c001');INSERT INTO c_product(pid,pname,price,category_id) VALUES('p004','JACK JONES','800','c002');
INSERT INTO c_product(pid,pname,price,category_id) VALUES('p005','真维斯','200','c002');
INSERT INTO c_product(pid,pname,price,category_id) VALUES('p006','花花公子','440','c002');
INSERT INTO c_product(pid,pname,price,category_id) VALUES('p007','劲霸','2000','c002');INSERT INTO c_product(pid,pname,price,category_id) VALUES('p008','香奈儿','800','c003');
INSERT INTO c_product(pid,pname,price,category_id) VALUES('p009','相宜本草','200','c003');SELECT * FROM c_product;-- 声明外键约束
ALTER TABLE c_product ADD FOREIGN KEY(category_id) REFERENCES category(cid); -- 因为从表product有主表category的引用数据,所以在主表中是无法直接
-- 删除与从表有关联的数据
DELETE FROM category WHERE cid='c002';-- 要想删除,只有解除主从表的约束关系
ALTER TABLE c_product DROP FOREIGN KEY category_id;
-- 或者先删除从表中与主表有关系的数据,再删除主表中的数据

4.4.7 删除数据

/*删除表中的数据格式:delete from 表名 where 条件drop table 表名 删除整个数据表
*/
-- 删除热水器
DELETE FROM product WHERE id=8;

5、JDBC
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。

5.1.1 简单的JDBC操作数据库

example 1 插入数据

package cn.itcast.demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;import com.mysql.jdbc.Driver;/** JDBC操作数据库的步骤:* 1、注册驱动*  告知JVM使用的是哪一个数据库的驱动* 2、获得连接*  使用JDBC中的类,完成对MySQL数据库的连接* 3、获得语句执行平台*  通过连接对象获取对SQL语句的执行者对象* 4、执行sql语句*  使用执行者对象,向数据库执行sql语句*  获取到数据库的执行后的结果* 5、处理结果* 6、释放资源(一堆close())* * * */
public class JDBCDemo {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1、注册驱动反射技术,将驱动类加入到内存//使用java.sql.DriverManager类静态方法registerDriver(Driver driver)//Driver是一个接口,参数传递,Mysql驱动程序中的实现类//使用DriverManager.registerDriver(new Driver)这种方式通过读源码发现注册2次驱动,所以不建议这种方式//  DriverManager.registerDriver(new Driver());Class.forName("com.mysql.jdbc.Driver");//2、获得数据库连接DriverManager类中静态方法//static Connection getConnection(String url,String user,String password)//返回值是Connection接口的实现类,在mysql驱动程序中//url:数据库地址   格式:jdbc:mysql://连接主机IP:端口号/数据库名字String url="jdbc:mysql://localhost:3306/mybase";String username="root";String password="123456";Connection con=DriverManager.getConnection(url, username, password);//3、获得语句执行平台,通过数据库连接对象,获取到sql语句的执行者对象//con对象调用方法 statement createStatement() 获取statement对象,将sql语句发送到数据库//返回值是statement接口的实现类对象,在mysql驱动程序中Statement stat=con.createStatement(); //4、执行sql语句//通过执行者对象调用方法执行sql语句,获取结果//int executeUpdate(String sql)执行数据库中的sql语句,insert delete update//返回值int 操作成功数据表多少行int row=stat.executeUpdate("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽车用品',50000,'疯狂涨价')");System.out.println(row);//6、释放资源  一堆close()stat.close();con.close();}
}

example2 查询数据

package cn.itcast.demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class JDBCDemo1 {public static void main(String[] args)throws Exception {// TODO Auto-generated method stub//1、注册驱动Class.forName("com.mysql.jdbc.Driver");//2、获取连接String url="jdbc:mysql://localhost:3306/mybase";String user="root";String password="123456";Connection con=DriverManager.getConnection(url, user, password);//3、获得数据库执行者对象Statement stat=con.createStatement();//4、执行sql语句获取结果集//ResultSet executeQuery(String sql)执行sql语句中的select查询//返回值ResultSet接口的实现类对象,实现类在mysql驱动中String sql="SELECT * FROM sort";ResultSet rs=stat.executeQuery(sql);//5、处理结果集,返回为真的时候说明有查询有结果,返回为假的时候则该查询没有结果,也就是不存在符合该查询的数据while(rs.next()) {//获取每列数据,使用的是ResultSet接口中的方法getXX方法参数,建议写String列名System.out.println(rs.getInt("sid")+"  "+rs.getString("sname")+"   "+rs.getDouble("sprice")+"   "+rs.getString("sdesc"));}rs.close();stat.close();}}

5.1.2 sql预编译存储式操作数据库(防注入攻击)

容易注入攻击

package cn.itcast.demo;
//sql注入攻击用户登陆
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;public class JDBCDemo3 {public static void main(String[] args) throws Exception {// TODO Auto-generated method stub//1、注册驱动Class.forName("com.mysql.jdbc.Driver");//2、获取连接String url="jdbc:mysql://localhost:3306/mybase";String user="root";String password="123456";Connection con=DriverManager.getConnection(url, user, password);//3、获取sql的执行对象Statement stat=con.createStatement();//4、执行sql语句,获取结果集,查询Scanner sc=new Scanner(System.in);String us=sc.nextLine();String pass=sc.nextLine();String sql="SELECT * FROM users WHERE username='"+us+"' AND PASSWORD='"+pass+"'";ResultSet rs=stat.executeQuery(sql);while(rs.next()) {/** 当这么写的时候就注入攻击成功:* adfafa* dasfafdas 'or'1=1* * */System.out.println(rs.getString("username")+"   "+rs.getString("password"));}rs.close();stat.close();con.close();}}

防注入攻击

package cn.itcast.demo;
/** java程序实现用户登陆,用户名和密码,数据库检查* 防止注入攻击* statement接口实现类,作用是执行sql语句,返回结果集* 有一个子接口PrepareStatement(sql预编译存储,多次高效的执行sql)* PrepareStatement的实现类也在驱动中,如何获取接口的实现类* * 是Connection数据连接对象的方法* PrepareStatement prepareStatement(String sql)* * */
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;public class JDBCDemo2 {public static void main(String[] args) throws Exception {// TODO Auto-generated method stub//1、注册驱动Class.forName("com.mysql.jdbc.Driver");//2、获取连接String url="jdbc:mysql://localhost:3306/mybase";String user="root";String password="123456";Connection con=DriverManager.getConnection(url, user, password);//4、执行sql语句,获取结果集,查询Scanner sc=new Scanner(System.in);String us=sc.nextLine();String pass=sc.nextLine();String sql="SELECT * FROM users WHERE username=? AND PASSWORD=?";//获取sql的执行对象,调用Connection接口的方法PrepareStatement,获取prepareStatement接口的实现类//方法中参数,sql语句中的参数全部采用问号占位符PreparedStatement pst=con.prepareStatement(sql);//调用pst对象set方法,设置问号占位符上的参数pst.setObject(1, us);pst.setObject(2, pass);//调用方法,执行sql,获取结果集ResultSet rs=pst.executeQuery();//之所以这里面不用放sql语句是因为con.prepareStatement(sql)已经编译好了while(rs.next()) {System.out.println(rs.getString("username")+"   "+rs.getString("password"));}rs.close();pst.close();con.close();}}

更新数据操作

package cn.itcast.demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;public class JDBCDemo4 {public static void main(String[] args) throws Exception{// TODO Auto-generated method stub/** 使用PrepareStatement接口,实现数据表的更新操作* * */Class.forName("com.mysql.jdbc.Driver");String url="jdbc:mysql://localhost:3306/mybase";String user="root";String password="123456";Connection con=DriverManager.getConnection(url, user, password);//拼写修改的sql语句,采用?占位String sql="UPDATE sort SET sname=?,sprice=? WHERE sid=?";//调用数据库连接对象con的方法prepareStatement获取sql语句的编译对象PreparedStatement pst=con.prepareStatement(sql);//调用pst的方法setXXX设置?占位pst.setObject(1, "汽车美容");pst.setObject(2, 4999988);pst.setObject(3, 7);//调用pst方法执行sql语句pst.executeUpdate();pst.close();con.close();}}

数据查询

package cn.itcast.demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;public class JDBCDemo5 {public static void main(String[] args) throws Exception{// TODO Auto-generated method stub/** 使用PrepareStatement接口,实现数据表的查询操作* * */Class.forName("com.mysql.jdbc.Driver");String url="jdbc:mysql://localhost:3306/mybase";String user="root";String password="123456";Connection con=DriverManager.getConnection(url, user, password);//拼写修改的sql语句,采用?占位String sql="SELECT * FROM sort";//调用数据库连接对象con的方法prepareStatement获取sql语句的编译对象PreparedStatement pst=con.prepareStatement(sql);//调用pst方法执行sql语句ResultSet rs=pst.executeQuery();while(rs.next()) {System.out.println(rs.getString("sid")+"   "+rs.getString("sname")+"   "+rs.getString("sprice")+"   "+rs.getString("sdesc"));}rs.close();pst.close();con.close();}}

封装查询到的数据
Sort.java

package cn.itcast.domain;public class Sort {private int sid;private String sname;private double sprice;private String sdesc;public Sort(int sid, String sname, double sprice, String sdesc) {this.sid = sid;this.sname = sname;this.sprice = sprice;this.sdesc = sdesc;}public Sort() {super();// TODO Auto-generated constructor stub}public int getSid() {return sid;}public void setSid(int sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public double getSprice() {return sprice;}public void setSprice(double sprice) {this.sprice = sprice;}public String getSdesc() {return sdesc;}public void setSdesc(String sdesc) {this.sdesc = sdesc;}@Overridepublic String toString() {return "Sort [sid=" + sid + ", sname=" + sname + ", sprice=" + sprice + ", sdesc=" + sdesc + "]";}}
package cn.itcast.demo2;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;import cn.itcast.domain.Sort;
import cn.itcast.jdbcutil.JDBCUtils;/** JDBC读取数据表sort,每行数据封装到sort类的对象中* 很多个Sort类对象,存储到List集合中* * */public class JDBCDemo1 {public static void main(String[] args) throws Exception {//使用JDBC工具类,直接获取数据库连接对象Connection con=JDBCUtils.getConnection();//连接获取数据库sql语句执行者对象PreparedStatement pst=con.prepareStatement("SELECT * FROM sort");//调用查询方法,获取结果集ResultSet rs=pst.executeQuery();//创建集合对象List<Sort>list=new ArrayList<Sort>();while(rs.next()) {//获取到每个列数据,封装到Sort对象中Sort s=new Sort(rs.getInt("sid"),rs.getString("sname"),rs.getDouble("sprice"),rs.getString("sdesc"));//封装的sort对象,存储到集合中list.add(s);}JDBCUtils.close(con, rs, pst);//遍历List集合for(Sort s:list) {System.out.println(s);}}}

加载配置文件的方式连接数据库

database.properties

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybase
username=root
password=123456
package cn.itcast.demo2;import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/** 加载properties配置文件* IO读取文件,键值对存储到集合* 从集合中以键值对方式获取数据库的连接信息,完成数据库的连接* * */
public class PropertiesDemo {public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {// TODO Auto-generated method stub//使用类的加载器InputStream in=PropertiesDemo.class.getClassLoader().getResourceAsStream("database.properties");System.out.println(in);Properties pro=new Properties();pro.load(in);//获取集合中的键值对String driverClass=pro.getProperty("driverClass");String url=pro.getProperty("url");String username=pro.getProperty("username");String password=pro.getProperty("password");Class.forName(driverClass);Connection con=DriverManager.getConnection(url, username, password);System.out.println(con);}}

5.2 使用DBUtils工具操作数据库

自定义数据库连接类JDBCUtils.java

package cn.itcast.jdbcutil;import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;/** 编写JDBC的工具类,获取数据库的连接对象采用* 采用读取配置文件的方式* 读取文件获取连接,执行一次,采用static代码块,* * */
public class JDBCUtilsConfig {private static Connection con;private static String driverClass;private static String url;private static String username;private static String password;static {try {readConfig();Class.forName(driverClass);con=DriverManager.getConnection(url, username, password);}catch(Exception e) {throw new RuntimeException("数据库连接失败");}}private static void readConfig() throws Exception{InputStream in=JDBCUtilsConfig.class.getClassLoader().getResourceAsStream("database.properties");Properties pro=new Properties();pro.load(in);driverClass=pro.getProperty("driverClass");url=pro.getProperty("url");username=pro.getProperty("username");password=pro.getProperty("password");}public static Connection getConnection() {return con;}
}

DBUtils增删改数据库

package cn.itcast.demo2;import java.sql.Connection;
import java.sql.SQLException;import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;import cn.itcast.jdbcutil.JDBCUtils;
import cn.itcast.jdbcutil.JDBCUtilsConfig;/** 使用QueryRunner类实现对数据表的insert delete update* 调用QueryRunner类的方法 update(Connection con,String sql,Object...param)* Object...param是可变参数,Object类型,sql语句会出现?占位符* * */public class QueryRunnerDemo {private static Connection con=JDBCUtilsConfig.getConnection();public static void main(String[] agrs) throws SQLException {//insert();
//      update();delete();}/** 定义方法,使用QueryRunner类的方法update向数据表中添加数据* */public static void insert() throws SQLException {//创建QueryRunner类对象QueryRunner qr=new QueryRunner();String sql="INSERT INTO sort(sname,sprice,sdesc) VALUES(?,?,?)";//将三个?占位符的实际参数,写在数组中Object[] params= {"体育用品",275.32,"购买体育用品"};//调用QueryRunner类的方法update执行sql语句int row=qr.update(con,sql,params);System.out.println(row);DbUtils.closeQuietly(con);}/** 定义方法,使用QueryRunner类的方法update将数据表的数据修改* */public static void update() throws SQLException {//创建QuerRunner类对象QueryRunner qr=new QueryRunner();//写修改数据的sql语句String sql="UPDATE sort SET sname=?,sprice=?,sdesc=? WHERE sid=?";//定义Object数组,存储?中的参数Object[] params= {"花卉",100.88,"情人节玫瑰花",4};//调用QueryRunner方法updateint row=qr.update(con,sql,params);System.out.println(row);}/** 定义方法,使用QueryRunner类的方法delete将数据表的数据删除* * */public static void delete() throws SQLException {QueryRunner qr=new QueryRunner();String sql="DELETE FROM sort WHERE sid=?";int row=qr.update(con, sql,7);System.out.println(row);DbUtils.closeQuietly(con);}
}

DBUtils进行数据库的数据查询

package cn.itcast.demo2;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import cn.itcast.domain.Sort;
import cn.itcast.jdbcutil.JDBCUtilsConfig;/** QueryRunner数据查询操作:* 调用QueryRunner类方法query(Connection con,String sql,ResultSetHandler r,Object...params)* ResultSetHandler r结果集的处理方式,传递ResultSetHandler接口实现类* Object..params SQL语句中的?占位符* * 注意:query方法返回值,返回的是T 泛型,具体返回值类型,跟随结果集处理方式变化* * * */
public class QueryRunnerDemo1 {private static Connection con=JDBCUtilsConfig.getConnection();public static void main(String[] args) throws SQLException {// TODO Auto-generated method stub
//      arrayHandler();
//      arrayListHandler();
//      beanHandler();
//      beanListHandler();
//      columnListHandler();
//      scalarHandler();
//      mapHandler();mapListHandler();}/** 结果集第一种处理方式:ArrayHandler* 将结果集的第一行存储到对象数组中 Object[]* 注意:被封装成数据到JavaBean对象,Sort类必须有空参构造函数,因为query是调用空参构造函数进行初始化的* */public static void arrayHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用方法query执行查询,传递连接对象,sql语句,结果集处理方式的实现类//返回对象数组Object[] result=qr.query(con,sql,new ArrayHandler());for(Object obj:result) {System.out.print(obj);}}/** 结果集第二种处理方法:ArrayListHandler* 将结果集的每一行封装到对象数组中,出现很多对象数组,对象数组存储到List集合* * */public static void arrayListHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用query方法,结果集处理的参数上,传递实现ArrayListHandler()List<Object[]>result=qr.query(con, sql, new ArrayListHandler());for(Object[] objs:result) {//遍历对象数组for(Object obj:objs) {System.out.print(obj+"   ");}System.out.println();}}/** 结果集第三种处理方法:BeanHandler* 将结果的第一行数据,封装成JavaBean对象* * */public static void beanHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用方法传递结果集实现类BeanHandlerSort s=qr.query(con, sql, new BeanHandler<Sort>(Sort.class));System.out.println(s);}/** 结果集第四种处理方式,BeanListHandler* 将数据结果集的每一行数据封装成JavaBean对象* 多个JavaBean对象封装到List集合中* * */public static void beanListHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用方法传递结果集的实现类BeanListHandlerList<Sort>list=qr.query(con,sql,new BeanListHandler<Sort>(Sort.class));for(Sort s: list) {System.out.println(s);}}/** 结果处理第五种方法,ColumnListHandler* 结果集,指定列的数据,存储到List集合* List<Object>每个列数据类型不同* * */public static void columnListHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用方法query,传递结果集实现类ColumnListHandler//实现类构造方法中,使用字符串的列名List<Object>list=qr.query(con, sql,new ColumnListHandler<Object>("sname"));for(Object obj:list) {System.out.println(obj);}}/** 结果集第六种方法,ScalarHandler* 对于查询后只有一个结果* * */public static void scalarHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用query,传递结果集处理实现类ScalarHandlerLong count=qr.query(con,sql,new ScalarHandler<Long>());System.out.println(count);}/** 结果集第七种处理方法,MapHandler* 将结果集的第一行数据封装到Map集合中* Map<键,值>  键:列名   值:这列的数据* * */public static void mapHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用方法query传递结果集实现类MapHandler//返回值:Map集合,Map接口实现类,泛型Map<String,Object>map=qr.query(con, sql, new MapHandler());//遍历Map集合for(String key:map.keySet()) {System.out.println(key+".."+map.get(key));}}/** 结果集的第八种处理方法,MapListHandler* 将结果集每一行存储到Map集合,键:列名,值:数据* Map集合过多,存储到List集合* */public static void mapListHandler() throws SQLException {QueryRunner qr=new QueryRunner();String sql="SELECT * FROM sort";//调用方法query,传递结果集实现类MapListHandler//返回值List集合,存储的是Map集合List<Map<String,Object>>list=qr.query(con,sql,new MapListHandler());//遍历集合listfor(Map<String,Object>map:list) {for(String key:map.keySet()) {System.out.println(key+"..."+map.get(key));}System.out.println();}}
}

5.3 dbcp连接池实现数据库的连接


package cn.itcast.demo3;import java.sql.Connection;import org.apache.commons.dbcp.BasicDataSource;public class DataSourceDemo {/** 连接池jar包中定义好一个类BasicDataSource* 实现类数据源的规范接口javax.sql.DataSource* * */public static void main(String args[]) {//创建DataSource接口的实现类对象//实现类BasicDataSource dataSource=new BasicDataSource();//连接数据库的4个最基本信息,通过对象方法setXXX设置进来dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mybase");dataSource.setUsername("root");dataSource.setPassword("123456");try {//调用对象方法getConnection获取数据库的连接Connection con=dataSource.getConnection();System.out.println(con);}catch(Exception e) {throw new RuntimeException("数据库连接失败");}}
}

自定义dbcp连接池工具类
JDBCUtils1.java

package cn.itcast.demo3;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSource;/** 自定义dbcp连接池的工具类* * */
public class JDBCUtils1 {//创建出BasicDataSource类对象private static BasicDataSource datasource=new BasicDataSource();//静态代码块,对象BasicDataSource对象中的配置,自定义static {datasource.setDriverClassName("com.mysql.jdbc.Driver");datasource.setUrl("jdbc:mysql://localhost:3306/mybase");datasource.setUsername("root");datasource.setPassword("123456");//对象连接池中的连接数量配置datasource.setInitialSize(10);//初始化的连接数datasource.setMaxActive(8);//最大连接数datasource.setMaxIdle(5);//最大空闲数datasource.setMinIdle(1);//最小空闲数}//定义静态方法,返回BasicDataSource类的对象public static DataSource getDataSource() {return datasource;}}

DBUtils+dbcp连接池实现数据库的操作

package cn.itcast.demo3;import java.util.List;import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;/** 测试写好的工具类* 提供的是一个DataSource接口的数据源* QueryRunner类构造方法,接收DataSource接口的实现类* 后面调用方法updata,query,无需传递他们Connection连接对象* * * */
public class QueryRunnerDemo {//定义2个方法,实现数据表的添加,数据表查询//QueryRunner类对象,写在类成员位置public static void main(String[] args) {// TODO Auto-generated method stub//      insert();select();}private static QueryRunner qr=new QueryRunner(JDBCUtils1.getDataSource());//数据表添加数据public static void insert() {String sql="INSERT INTO sort(sname,sprice,sdesc) VALUES(?,?,?)";Object[]params= {"水果",100.12,"刚刚上市的核桃"};try {int row=qr.update(sql, params);System.out.println(row);}catch(Exception e) {throw new RuntimeException("数据添加失败");}}//数据表的查询public static void select() {String sql="SELECT * FROM sort";try {List<Object[]>list=qr.query(sql,new ArrayListHandler());for(Object[] objs:list) {for(Object obj:objs) {System.out.println(obj+"\t");}System.out.println();}}catch(Exception e){throw new RuntimeException("查询失败");}}}

自定义连接池

package cn.itcast.demo4;import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;import javax.sql.DataSource;import cn.itcast.jdbcutil.JDBCUtils;
/** 自定义连接池* * */
public class MyDataSource implements DataSource {//1、创建1个容器用于存储Connection对象private static LinkedList<Connection> pool=new LinkedList<Connection>();//2、创建5个连接放到容器中去static {for(int i=0;i<5;i++) {Connection conn=JDBCUtils.getConnection();pool.add(conn);}}@Overridepublic Connection getConnection() throws SQLException {// TODO Auto-generated method stubConnection conn=null;//3、使用前先判断if(pool.size()==0) {//4、池子里面没有我们再创建一些for(int i=0;i<5;i++) {conn=JDBCUtils.getConnection();pool.add(conn);}}//5、从池子里面获取一个连接对象Connectionconn=pool.remove(0);return conn;}/** 归还连接对象到连接池中去* */public void backConnection(Connection conn) {pool.add(conn);}@Overridepublic PrintWriter getLogWriter() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {// TODO Auto-generated method stub}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {// TODO Auto-generated method stub}@Overridepublic int getLoginTimeout() throws SQLException {// TODO Auto-generated method stubreturn 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {// TODO Auto-generated method stubreturn null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic Connection getConnection(String username, String password) throws SQLException {// TODO Auto-generated method stubreturn null;}
}

采用装饰器模式自定义连接池

JDBCUtils.java

package cn.itcast.jdbcutil;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;/** 实现JDBC的工具类* 定义方法,直接返回数据库的连接对象* * 定义方法,关闭对象* */
public class JDBCUtils {private JDBCUtils() {}private static Connection con;static {try {Class.forName("com.mysql.jdbc.Driver");String url="jdbc:mysql://localhost:3306/mybase";String user="root";String password="123456";con=DriverManager.getConnection(url,user,password);}catch(Exception e) {throw new RuntimeException(e+"数据库连接失败");}}/** 定义静态方法,返回数据库的连接对象* */public static Connection getConnection() {return con;}public static void close(Connection con,ResultSet rs,Statement stat) {if(rs!=null) {try {rs.close();}catch(SQLException e) {}}if(stat!=null) {try {stat.close();}catch(SQLException e) {}}if(con!=null) {try {con.close();}catch(SQLException e) {}}}public static void close(Connection con,Statement stat) {if(stat!=null) {try {stat.close();}catch(SQLException e) {}}if(con!=null) {try {con.close();}catch(SQLException e) {}}}
}

MyConnection.java

package cn.itcast.demo4;import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
/** 装饰器模式* * */
//1、实现同一个接口Connection
public class MyConnection implements Connection{//3、定义一个变量private Connection conn;private LinkedList<Connection>pool;//2、编写一个构造方法(参数使用了面向对象的多态性)public MyConnection(Connection conn,LinkedList<Connection>pool) {this.conn=conn;this.pool=pool;}//4、书写需要增强的方法@Overridepublic void close() throws SQLException {// TODO Auto-generated method stubpool.add(conn);}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic Statement createStatement() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic String nativeSQL(String sql) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {// TODO Auto-generated method stub}@Overridepublic boolean getAutoCommit() throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic void commit() throws SQLException {// TODO Auto-generated method stub}@Overridepublic void rollback() throws SQLException {// TODO Auto-generated method stub}@Overridepublic boolean isClosed() throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {// TODO Auto-generated method stub}@Overridepublic boolean isReadOnly() throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic void setCatalog(String catalog) throws SQLException {// TODO Auto-generated method stub}@Overridepublic String getCatalog() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setTransactionIsolation(int level) throws SQLException {// TODO Auto-generated method stub}@Overridepublic int getTransactionIsolation() throws SQLException {// TODO Auto-generated method stubreturn 0;}@Overridepublic SQLWarning getWarnings() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void clearWarnings() throws SQLException {// TODO Auto-generated method stub}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Map<String, Class<?>> getTypeMap() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {// TODO Auto-generated method stub}@Overridepublic void setHoldability(int holdability) throws SQLException {// TODO Auto-generated method stub}@Overridepublic int getHoldability() throws SQLException {// TODO Auto-generated method stubreturn 0;}@Overridepublic Savepoint setSavepoint() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Savepoint setSavepoint(String name) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void rollback(Savepoint savepoint) throws SQLException {// TODO Auto-generated method stub}@Overridepublic void releaseSavepoint(Savepoint savepoint) throws SQLException {// TODO Auto-generated method stub}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,int resultSetHoldability) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,int resultSetHoldability) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Clob createClob() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Blob createBlob() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic NClob createNClob() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic SQLXML createSQLXML() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic boolean isValid(int timeout) throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic void setClientInfo(String name, String value) throws SQLClientInfoException {// TODO Auto-generated method stub}@Overridepublic void setClientInfo(Properties properties) throws SQLClientInfoException {// TODO Auto-generated method stub}@Overridepublic String getClientInfo(String name) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Properties getClientInfo() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setSchema(String schema) throws SQLException {// TODO Auto-generated method stub}@Overridepublic String getSchema() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void abort(Executor executor) throws SQLException {// TODO Auto-generated method stub}@Overridepublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {// TODO Auto-generated method stub}@Overridepublic int getNetworkTimeout() throws SQLException {// TODO Auto-generated method stubreturn 0;}}

定义连接池

package cn.itcast.demo4;import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;import javax.sql.DataSource;import cn.itcast.jdbcutil.JDBCUtils;
/** 自定义连接池* * */
public class MyDataSource1 implements DataSource {//1、创建1个容器用于存储Connection对象private static LinkedList<Connection> pool=new LinkedList<Connection>();//2、创建5个连接放到容器中去static {for(int i=0;i<5;i++) {Connection conn=JDBCUtils.getConnection();//放入池子中connection对象已经经过改造了MyConnection myconn=new MyConnection(conn,pool);pool.add(myconn);}}@Overridepublic Connection getConnection() throws SQLException {// TODO Auto-generated method stubConnection conn=null;//3、使用前先判断if(pool.size()==0) {//4、池子里面没有我们再创建一些for(int i=0;i<5;i++) {conn=JDBCUtils.getConnection();//放入池子中connection对象已经经过改造了MyConnection myconn=new MyConnection(conn,pool);pool.add(myconn);}}//5、从池子里面获取一个连接对象Connectionconn=pool.remove(0);return conn;}/** 归还连接对象到连接池中去* */public void backConnection(Connection conn) {pool.add(conn);}@Overridepublic PrintWriter getLogWriter() throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {// TODO Auto-generated method stub}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {// TODO Auto-generated method stub}@Overridepublic int getLoginTimeout() throws SQLException {// TODO Auto-generated method stubreturn 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {// TODO Auto-generated method stubreturn null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {// TODO Auto-generated method stubreturn false;}@Overridepublic Connection getConnection(String username, String password) throws SQLException {// TODO Auto-generated method stubreturn null;}
}

5.4 C3P0连接池(常用,因为它只要修改配置就可以轻松的更换数据库以及用户)

c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><default-config><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql:///mybase</property><property name="user">root</property><property name="password">123456</property><property name="initialPoolSize">5</property><property name="maxPoolSize">20</property></default-config><named-config name="ctgu"> <property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql:///mybase</property><property name="user">root</property><property name="password">123456</property></named-config></c3p0-config>
package cn.itcast.C3P0;import java.sql.Connection;
import java.sql.SQLException;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class C3P0Utils {private static ComboPooledDataSource dataSource=new ComboPooledDataSource();//使用的默认配置//private static ComboPooledDataSource dataSource=new ComboPooledDataSource("ctgu");//使用的自定义配置public static DataSource getDataSource() {return dataSource;}public static Connection getConnection() {try {return dataSource.getConnection();}catch(SQLException e) {throw new RuntimeException(e);}}
}

案例应用——管家婆记账软件

常用的项目分析逻辑


view层作用: 视图层,即项目中的界面
controller层作用: 控制层, 获取界面上的数据,为界面设置数据; 将要实现的功能交给业务层处理
service层作用: 业务层, 功能的实现, 与controller控制层和数据访问层DAO交互, 将对数据库的操作交给DAO数据访问层来处理
dao层作用: 数据访问层, 用来操作数据库表的数据
db数据库: 这里指MySQL
domain 实体包: 存放JavaBean
tools工具包:存放项目中使用到的工具类
test 测试包: 存放项目功能测试的代码

功能界面菜单

界面菜单的完成,是项目编写的第一步。
我们通过输出语句,完成界面菜单的输出,之后再根据输入的功能序号,进行对应功能的调用执行。

功能实现步骤
1编写MainView类run方法
1.1完成功能界面菜单显示
1.2接收键盘输入的功能选项
1.3根据选项值,调用对应的功能方法
2编写MainApp类的main主方法
2.1调用MainView类中run方法,实现将程序执行起来,显示功能界面菜单。

MainApp.java

package cn.ctgu.gjp.app;import cn.ctgu.gjp.view.MainView;/** 主程序类:开启软件安程序* */
public class MainApp {public static void main(String[] args) {// TODO Auto-generated method stubnew MainView().run();}}

MainView.java

package cn.ctgu.gjp.view;import java.util.List;
import java.util.Scanner;import cn.ctgu.gjp.controller.ZhangWuController;
import cn.ctgu.gjp.domain.ZhangWu;/** 视图层,用户看到和操作的界面* 数据传递给controller层实现* 成员位置:创建controller对象* * */
public class MainView {private ZhangWuController controller=new ZhangWuController();/** 实现界面效果* 接收用户的输入* 根据数据,调用不同的功能方法* * */public void run() {/** 创建Scanner类对象,反复键盘输入* */Scanner sc=new Scanner(System.in);while(true) {System.out.println("-------管家婆家庭记账软件--------");System.out.println("1.添加账务 2.编辑账务 3.删除账务 4.查询账务 5.退出系统");System.out.println("请输入要操作的功能序号[1-5]:");//接受用户的菜单选择int choose=sc.nextInt();//对选择的菜单判断,调用不同的功能switch(choose) {case 1://选择添加账务,调用添加账务的方法addZhangWu();break;case 2://选择编辑账务,调用编辑账务的方法editZhangWu();break;case 3://选择删除账务,调用删除账务的方法deleteZhangWu();break;case 4://选择查询账务,调用查询账务的方法selectZhangWu();break;case 5:System.exit(0);break;}}}/** 定义方法实现对账务的删除* 实现思想:*  接收用户的输入,输入一个主键数据*  调用控制层,传递一个主键* * */public void deleteZhangWu() {//调用查询所有账务数据的功能,显示出来//看到所有数据,从中选择一项进行修改selectAll();System.out.println("选择的是删除功能,请输入ID号:");int zwid=new Scanner(System.in).nextInt();//调用控制层方法,传递主键id即可controller.deleteZhangWu(zwid);System.out.println("删除账务成功");}/** 定义方法,实现对账务的编辑功能* 实现思想:*      接收用户的输入*      数据的信息,封装成ZhangWu对象*      调用控制层的方法,传递ZhangWu对象,实现编辑* * */public void editZhangWu() {//调用查询所有账务数据的功能,显示出来//看到所有数据,从中选择一项进行修改selectAll();System.out.println("选择的是编辑功能,请输入数据");Scanner sc=new Scanner(System.in);//接收用户的数据System.out.println("输入ID:");int zwid=sc.nextInt();System.out.println("输入分类名称:");String flname=sc.next();System.out.println("输入金额:");double money=sc.nextDouble();System.out.println("输入账户:");String zhanghu=sc.next();System.out.println("输入日期:格式XXX-XX-XX");String createtime=sc.next();System.out.println("输入具体描述:");String description=sc.next();//将所有用户输入的数据封装到ZhangWu对象中//输入的ID,必须封装对象ZhangWu zw=new ZhangWu(zwid, flname, money, zhanghu, createtime, description);//调用controller层中的方法,实现编辑账务controller.editZhangWu(zw);System.out.println("账务编辑成功!");}/** 定义方法 addZhangWu* 添加账务的方法,用户在界面中选择菜单1的时候调用* 实现思想:*  接收键盘输入,5项输入,调用controller层方法* */public void addZhangWu() {System.out.println("选择的添加账务功能,请输入一下内容");Scanner sc=new Scanner(System.in);System.out.println("输入分类名称:");String flname=sc.next();System.out.println("输入金额:");double money=sc.nextDouble();System.out.println("输入账户:");String zhanghu=sc.next();System.out.println("输入日期:格式XXX-XX-XX");String createtime=sc.next();System.out.println("输入具体描述:");String description=sc.next();//将接收到的数据调用controller层的方法,传递参数实现数据添加ZhangWu zw=new ZhangWu(0, flname, money, zhanghu, createtime, description);controller.addZhangWu(zw);System.out.println("添加账务成功!");}/** 定义方法selectZhangWu()* 显示查询的方式1所有查询   2条件查询* * */public void selectZhangWu() {System.out.println("1.查询所有    2.条件查询");Scanner sc=new Scanner(System.in);int selectChooser=sc.nextInt();//判断根据用户的选择,调用不同的功能switch(selectChooser) {case 1://选择的查询所有,调用查询所有的方法selectAll();break;case 2://选择条件查询,调用带有查询条件的方法select();break;}}/** 定义方法实现查询所有的账务数据* */public void selectAll() {//调用控制层中的方法,查询所有的账务数据List<ZhangWu>list=controller.selectAll();print(list);}/** 定义方法实现条件查询账务数据* 提供用户的输入日期,开始日期结束日期* 就2个日期,传递到controller层* 调用controller的方法,传递2个日期参数* 获取到controller查询的结果集,打印出来* */public void select() {System.out.println("选择条件查询,输入日期格式XXXX-XX-XX");Scanner sc=new Scanner(System.in);System.out.println("请输入开始日期:");String startDate=sc.nextLine();System.out.println("请输入结束日期:");String endDate=sc.nextLine();//调用controller层的方法,传递日期,获取查询结果集List<ZhangWu>list=controller.select(startDate, endDate);if(list.size()!=0)print(list);elseSystem.out.println("没有查询到数据");}//输出账务数据方法,接收List集合,遍历集合,输出表格private void print(List<ZhangWu> list) {//输出表头System.out.println("ID\t类别\t账户\t金额\t时间\t说明");//遍历集合,结果输出控制台for(ZhangWu zw:list) {System.out.println(zw.getZwid()+"\t"+zw.getFlname()+"\t"+zw.getZhanghu()+"\t"+zw.getMoney()+"\t"+zw.getCreatetime()+"\t"+zw.getDescription());}}
}

查询所有账务

功能实现步骤
1编写MainView类中selectZhangWu方法
1.1通过输出语句,显示出要查询账务的方式
1.2接收键盘的输入项,调用对应的方法(1.查询所有 2.按条件查询)
2编写MainView类中selectAll查询所有账务方法
2.1调用ZhangWuService类selectAll方法,返回包含所有账务数据的List集合
2.2调用MainView类中print方法,实现控制台显示所有账务数据
3编写MainView类中print方法
3.1使用输出语句,打印出账务表的表头名称

3.2遍历账务集合,将每个账务信息输出打印
4编写ZhangWuService类中selectAll方法
4.1调用ZhangWuDao类中selectAll方法,返回包含所有账务数据的List集合
5编写ZhangWuDao类中selectAll()方法
5.1通过QueryRunner对象,调用query方法查询数据库表gjp_zhangwu,返回包含所有账务数据的List集合

多条件查询账务

功能分析
1编写MainView类中select方法
1.1通过键盘输入查询日期的范围
1.2调用ZhangWuSerice类中select方法,返回查询日期范围内的账务信息集合List
1.3调用MainView类中的print方法,将账务信息集合中的内容显示在控制台中
2编写ZhangWuService类中select方法
2.1调用ZhangWuDao 类中select方法,返回查询日期范围内的账务信息集合List
3编写ZhangWuDao类中select方法
通过QueryRunner对象,调用query方法查询数据库表gjp_zhangwu,返回包含查询日期范围内的账务数据List集合

ZhangWuService.java

package cn.ctgu.gjp.service;import java.util.List;import cn.ctgu.gjp.dao.ZhangWuDao;
import cn.ctgu.gjp.domain.ZhangWu;/** 业务层类* 接收上一层,控制层controller的数据* 经过计算,传递给dao层,操作数据库* 调用dao层中的类,类成员位置,创建dao类对象* * */
public class ZhangWuService {private ZhangWuDao dao=new ZhangWuDao();/** 定义方法,实现编辑账务* 由控制层调用,传递ZhangWu对象* 调用dao层的方法,传递ZhangWu对象* */public void editZhangWu(ZhangWu zw) {dao.editZhangWu(zw);}/** 定义方法,实现添加账务 * 是由控制层调用,传递ZhangWu类型对象* 调用dao层方法,传递ZhangWu对象* * */public void addZhangWu(ZhangWu zw) {dao.addZhangWu(zw);}/** 定义方法,实现条件查询账务* 方法由控制层调用,传递2个日期字符串* 调用dao层的方法,传递2个日期字符串* 获取到查询结果集* * */public List<ZhangWu>select(String startDate,String endDate){return dao.select(startDate,endDate);}/** 定义方法,实现查询所有的账务数据* 此方法由控制层调用,去调用dao层的方法* 返回存储账务的list集合* */public List<ZhangWu> selectAll() {return dao.selectAll();}public void deleteZhangWu(int zwid) {// TODO Auto-generated method stubdao.deleteZhangWu(zwid);}
}

ZhangWuDao.java

package cn.ctgu.gjp.dao;import java.sql.SQLException;
import java.util.List;import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;import cn.ctgu.gjp.domain.ZhangWu;
import cn.ctgu.gjp.tools.JDBCUtils;/** 实现对数据表gjp_zhangwu数据增删改查操作* dbutils工具类完成,类成员创建QueryRunnner对象,指定数据源* * */
public class ZhangWuDao {private QueryRunner qr=new QueryRunner(JDBCUtils.getDataSource());/** 定义方法,实现添加账务功能* 由业务层调用,传递ZhangWu对象* 将ZhangWu对象中的数据,添加到数据表* */public void addZhangWu(ZhangWu zw) {try {//拼写添加数据的sqlString sql="INSERT INTO gjp_zhangwu(flname,money,zhanghu,createtime,description)VALUES(?,?,?,?,?)";//创建对象数组,存储5个占位符的实际参数//实际参数来源是传递过来的对象的ZhangWuObject[]params= {zw.getFlname(),zw.getMoney(),zw.getZhanghu(),zw.getCreatetime(),zw.getDescription()};//调用qr对象中的方法update执行添加qr.update(sql,params);}catch(SQLException e) {System.out.println(e);throw new RuntimeException("账务添加失败");}}/** 定义方法,查询数据库,带有条件去查询账务表* 由业务层调用,查询结果集存储到Bean对象,存储到List集合* 调用者传递2个日期字符串* * */public List<ZhangWu>select(String startDate,String endDate){try {//拼写条件查询的sql语句String sql="SELECT * FROM gjp_zhangwu WHERE createtime BETWEEN ? AND ?";//定义对象数组,存储?占位符Object[]params= {startDate,endDate};//调用qr对象的方法query查询数据表,获取结果集return qr.query(sql, new BeanListHandler<ZhangWu>(ZhangWu.class),params);}catch(SQLException e) {System.out.println(e);throw new RuntimeException("条件查询失败");}}/** 定义方法,查询数据库,获取所有的账务数据* 方法由业务层调用* 结果集将所有的账务数据存储到Bean对象中,然后存储到集合中* * */public List<ZhangWu> selectAll() {try {//查询账务数据的sql语句String sql="SELECT * FROM gjp_zhangwu";//调用qr对象的方法,query方法,结果集BeanListHandlerList<ZhangWu>list=qr.query(sql, new BeanListHandler<>(ZhangWu.class));return list;}catch(Exception e) {System.out.println(e);throw new RuntimeException("查询所有账务失败");}}/** 定义方法实现编辑账务功能* 由业务层调用传递ZhangWu对象* 将对象中的数据更新到数据表* */public void editZhangWu(ZhangWu zw) {// TODO Auto-generated method stubtry {//更新数据的sqlString sql="UPDATE gjp_zhangwu SET flname=?,money=?,"+ "zhanghu=?,createtime=?,description=? WHERE zwid=?";//定义对象数组,将所有的参数放进去Object[]params= {zw.getZwid(),zw.getFlname(),zw.getMoney(),zw.getZhanghu(),zw.getCreatetime(),zw.getDescription()};//调用qr对象方法update执行更新qr.update(sql,params);}catch(SQLException e) {System.out.println(e);throw new RuntimeException("账务编辑失败");}}public void deleteZhangWu(int zwid) {// TODO Auto-generated method stubtry {//删除数据的sqlString sql="DELETE FROM gjp_zhangwu WHERE zwid=?";qr.update(sql,zwid);}catch(SQLException e) {System.out.println(e);throw new RuntimeException("删除账务失败");}}
}

添加账务

功能分析
1编写MainView类中addZhangWu方法
1.1键盘输入新添加的账务信息
1.2调用ZhangWuService类中addZhangWu方法,用来指定账务的添加
1.3添加完毕后,使用输出语句,提示“添加账务成功!”
2编写ZhangWuService类中addZhangWu方法
2.1调用ZhangWuDao类中addZhangWu方法,用来指定账务的添加
3编写ZhangWuDao类中addZhangWu方法
3.1通过QueryRunner对象,调用update方法更新数据库表gjp_zhangwu,完成指定账务添加到数据库表中

编辑账务

功能分析
1编写MainView类中editZhangWu方法
1.1键盘输入要编辑的账务信息ID号
1.2键盘输入要修改的账务信息内容
1.3调用ZhangWuService类中editZhangWu方法,用来将指定的账务信息进行更新
1.4更新完毕后,使用输出语句,提示 “编辑账务成功!”
2编写ZhangWuService类中editZhangWu方法
2.1调用ZhangWuDao类中editZhangWu方法,用来将指定的账务信息进行更新
3编写ZhangWuDao类中editZhangWu方法
3.1通过QueryRunner对象,调用update方法更新数据库表gjp_zhangwu,完成数据库表中指定账务更新操作

删除账务

功能分析
1编写MainView类中deleteZhangWu方法
1.1键盘输入要删除的账务信息ID号
1.2调用ZhangWuService类中deleteZhangWu方法,用来将指定的账务信息删除
1.3删除完毕后,使用输出语句,提示 “删除账务成功!”
2编写ZhangWuService类中deleteZhangWu方法
2.1调用ZhangWuDao类中deleteZhangWu方法,用来将指定的账务信息删除
3编写ZhangWuDao类中deleteZhangWu方法
3.1通过QueryRunner对象,调用update方法更新数据库表gjp_zhangwu,完成数据库表中指定账务删除操作

其他代码:
ZhangWuController.java

package cn.ctgu.gjp.controller;import java.util.List;import cn.ctgu.gjp.domain.ZhangWu;
import cn.ctgu.gjp.service.ZhangWuService;/** 控制器层* 接收视图层的数据,数据传递给service层* 成员位置,创建安service对象* * * */
public class ZhangWuController {private ZhangWuService service=new ZhangWuService();/** 定义方法实现删除功能*     由视图层调用,传递int类型主键*     调用service层方法,传递int主键* * */public void deleteZhangWu(int zwid) {service.deleteZhangWu(zwid);}/** 定义方法实现编辑账务功能* 由视图层调用,传递参数,也是ZhangWu对象* 调用Service层的方法,传递ZhangWu对象* */public void editZhangWu(ZhangWu zw) {service.editZhangWu(zw);}/** 定义方法,实现账务添加功能* 由视图层调用,传递参数(传递过来的参数不能是5个数据,传递的是1个ZhangWu类型的对象)* 方法调用service层的方法,传递ZhangWu对象,获取到添加后的结果集(添加成功的行数 int)* */public void addZhangWu(ZhangWu zw) {service.addZhangWu(zw);}/** 定义方法,实现条件查询账务* 方法由视图层调用,传递两个日期的字符串* 调用service层的方法,传递两个日期字符串,获取结果集* 结果集返回给视图* * * */public List<ZhangWu>select(String startDate,String endDate){return service.select(startDate, endDate);}/** 控制层类定义方法,实现查询所有的账务数据* 方法由视图层调用,方法调用service层* */public List<ZhangWu> selectAll() {return service.selectAll();}
}

ZhangWu.java(domain包中的JavaBean)

package cn.ctgu.gjp.domain;public class ZhangWu {private int zwid;private String flname;private double money; private String zhanghu; private String createtime;private String description;public ZhangWu(int zwid, String flname, double money, String zhanghu, String createtime, String description) {super();this.zwid = zwid;this.flname = flname;this.money = money;this.zhanghu = zhanghu;this.createtime = createtime;this.description = description;}public int getZwid() {return zwid;}public void setZwid(int zwid) {this.zwid = zwid;}public String getFlname() {return flname;}public void setFlname(String flname) {this.flname = flname;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public String getZhanghu() {return zhanghu;}public void setZhanghu(String zhanghu) {this.zhanghu = zhanghu;}public String getCreatetime() {return createtime;}public void setCreatetime(String createtime) {this.createtime = createtime;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public ZhangWu() {super();// TODO Auto-generated constructor stub}@Overridepublic String toString() {return "Zhangwu [zwid=" + zwid + ", flname=" + flname + ", money=" + money + ", zhanghu=" + zhanghu+ ", createtime=" + createtime + ", description=" + description + "]";} }

JDBCUtils.java(tools包中的工具类)

package cn.ctgu.gjp.domain;public class ZhangWu {private int zwid;private String flname;private double money; private String zhanghu; private String createtime;private String description;public ZhangWu(int zwid, String flname, double money, String zhanghu, String createtime, String description) {super();this.zwid = zwid;this.flname = flname;this.money = money;this.zhanghu = zhanghu;this.createtime = createtime;this.description = description;}public int getZwid() {return zwid;}public void setZwid(int zwid) {this.zwid = zwid;}public String getFlname() {return flname;}public void setFlname(String flname) {this.flname = flname;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public String getZhanghu() {return zhanghu;}public void setZhanghu(String zhanghu) {this.zhanghu = zhanghu;}public String getCreatetime() {return createtime;}public void setCreatetime(String createtime) {this.createtime = createtime;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public ZhangWu() {super();// TODO Auto-generated constructor stub}@Overridepublic String toString() {return "Zhangwu [zwid=" + zwid + ", flname=" + flname + ", money=" + money + ", zhanghu=" + zhanghu+ ", createtime=" + createtime + ", description=" + description + "]";} }

5.5 数据库的事务
1、什么是事务?
一件事情有n个组成单元,要不这个n个组成单元同时成功,要不n个单元就同时失败
也就是将n个组成单元放到一个事务中。
2、Mysql的事务
默认的事务:一条sql语句就是一个事务,默认就开启事务并提交事务
手动事务:
1、显示的开启一个事务:start transaction
2、事务提交:commit代表从开启事务到事务提交中间的所有的sql都认为有效

真正的更新事务:
3、事务的回滚:rollback代表事物的回滚,从开启事务到事务回滚,中间的所有的
sql操作都认为无效数据库,即没有被更新

总结:
Mysql的事务控制:
开启事务:start transaction
提交事务:commit
回滚事务:rollback

JDBC事务控制:开启事务:conn.setAutoCommit(false);提交事务:conn.commit();回滚事务:conn.rollback()DBUtils的事务控制也是通过jdbc
ThreadLocal:实现的是通过线程绑定的方式传递参数

1.事务的特性ACID
1)原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2)一致性(Consistency)一个事务中,事务前后数据的完整性必须保持一致。
3)隔离性(Isolation)多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的 事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
4)持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
2.并发访问问题—-由隔离性引起
如果不考虑隔离性,事务存在3中并发访问问题。
1)脏读:B事务读取到了A事务尚未提交的数据 —— 要求B事务要读取A事 务提交的数据
2)不可重复读:一个事务中 两次读取的数据的内容不一致 —– 要求的是一个事 务中多次读取时数据是一致的 — unpdate
3)幻读/虚读:一个事务中 两次读取的数据的数量不一致 —– 要求在一个事务多 次读取的数据的数量是一致的 –insert delete
3.事务的隔离级别
1)read uncommitted : 读取尚未提交的数据 :哪个问题都不能解决
2)read committed:读取已经提交的数据 :可以解决脏读 —- oracle默认的
3)repeatable read:重读读取:可以解决脏读 和 不可重复读 —mysql默认的
serializable:串行化:可以解决 脏读 不可重复读 和 虚读—相当于锁表

查看mysql数据库默认的隔离级别:select @@tx_isolation

设置mysql的隔离级别:set session transaction isolation level 设置事务隔离级别

隔离级别的性能:
read uncommitted>read committed>repeatable read>serialazable

安全性:read uncommitted<read committed<repeatable read<serialazable

JDBC控制事务

package cn.itcast.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class JDBCDemo {public static void main(String[] args) {//通过jdbc去控制事务Connection conn=null;try {//1、注册驱动Class.forName("com.mysql.jdbc.Driver");//2、获得Connectionconn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mybase", "root", "123456");//手动开启事务conn.setAutoCommit(false);//手动提交//3、获得执行平台Statement stmt=conn.createStatement();//4、操作sqlstmt.executeUpdate("insert into product values(9,'早餐','25','吃早饭')");//提交事务//执行sql的connection与开启事务的connection必须是同一个才能对事务进行控制conn.commit();stmt.close();conn.close();}catch(Exception e) {try {conn.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}
}

DBUtils工具控制事务

package cn.itcast.jdbc;import java.sql.Connection;
import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;import cn.itcast.demo3.JDBCUtils1;
import cn.itcast.jdbcutil.JDBCUtilsConfig;public class DBUtilsDemo {public static void main(String[] args) {Connection conn=null;try {QueryRunner qr=new QueryRunner();//获得一个Connectionconn=JDBCUtilsConfig.getConnection();//开启事务conn.setAutoCommit(false);qr.update(conn, "update product set sprice=100 where sid=8");//提交回滚事务conn.commit();}catch(SQLException e) {try {conn.rollback();}catch(SQLException e1) {e1.printStackTrace();}}}
}

事务隔离案例——转账

transfer.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body><form action="${pageContext.request.contextPath }/transferServlet" method="post">转出账户:<input type="text" name="out"/><br/>转入账户:<input type="text" name="in"/><br/>转账金额:<input type="text" name="money"/><input type="submit" value="确认转账"/></form>
</body>
</html>

transferServlet.java

package cn.ctgu.web;import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import cn.ctgu.service.TransferService;/*** Servlet implementation class transferServlet*/
@WebServlet("/transferServlet")
public class transferServlet extends HttpServlet {private static final long serialVersionUID = 1L;/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//接收转账的参数String out=request.getParameter("out");String in=request.getParameter("in");String moneyStr=request.getParameter("money");double money=Double.parseDouble(moneyStr);//调用业务层的转账方法TransferService service=new TransferService();boolean isTransferSuccess=service.transfer(out,in,money);response.setContentType("text/html;charset=utf-8");if(isTransferSuccess) {response.getWriter().write("转账成功!!!");}else {response.getWriter().write("转账失败!!!");}}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)*/protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}}

TransferService.java

package cn.ctgu.service;import java.sql.Connection;
import java.sql.SQLException;import cn.ctgu.dao.JDBCUtils;
import cn.ctgu.dao.TransferDao;public class TransferService {public boolean transfer(String out,String in,double money) {boolean transfersuccess=true;TransferDao dao=new TransferDao();Connection conn=null;try {conn=JDBCUtils.getConnection();//开启事务conn.setAutoCommit(false);//转入账户dao.out(conn,out,money);//转出账户dao.in(conn,in,money);}catch(Exception e) {transfersuccess=false;//回滚事务try {conn.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();throw new RuntimeException("转账失败");}}finally {try {conn.commit();//提交事务} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();throw new RuntimeException("转账失败");}}return transfersuccess;}}

TransferDao.java

package cn.ctgu.dao;import java.sql.Connection;
import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;public class TransferDao {public void out(Connection conn,String out,double money) throws SQLException {QueryRunner qr=new QueryRunner();Object[]params= {money,out};String sql= "UPDATE counts SET money=money-? WHERE cname=?";qr.update(conn,sql,params);}public void in(Connection conn,String in,double money) throws SQLException {QueryRunner qr=new QueryRunner();Object[]params= {money,in};String sql="UPDATE counts SET money=money+? WHERE cname=?";qr.update(conn,sql,params);}
}

通过 ThreadLocal改进的代码(推荐这种)

TransferService2.java

package cn.ctgu.service;import java.sql.Connection;
import java.sql.SQLException;import cn.ctgu.dao.JDBCUtils;
import cn.ctgu.dao.MyDataSourceUtils;
import cn.ctgu.dao.TransferDao2;public class TransferService2 {public boolean transfer(String out,String in,double money) {boolean transfersuccess=true;TransferDao2 dao=new TransferDao2();try {//开启事务MyDataSourceUtils.startTransaction();//转入账户dao.out(out,money);//转出账户dao.in(in,money);}catch(Exception e) {transfersuccess=false;//回滚事务try {MyDataSourceUtils.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();throw new RuntimeException("转账失败");}}finally {try {MyDataSourceUtils.commit();//提交事务} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();throw new RuntimeException("转账失败");}}return transfersuccess;}}

MyDataSourceUtils.java(关键代码,将一个连接放到一个线程中)

package cn.ctgu.dao;import java.sql.Connection;
import java.sql.SQLException;import com.mchange.v2.c3p0.ComboPooledDataSource;public class MyDataSourceUtils {//获得Connection  从连接池中获取private static ComboPooledDataSource dataSource=new ComboPooledDataSource();//创建ThreadLocalprivate static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();//开启事务public static void startTransaction() throws SQLException {Connection conn=getCurrentConnection();conn.setAutoCommit(false);}//获得当前线程绑定的connpublic static Connection getCurrentConnection() throws SQLException {//从ThreadLocal寻找当前线程是否有对应ConnectionConnection conn=tl.get();if(conn==null) {//获得新的connectionconn= getConnection();//将conn资源绑定到ThreadLocal(map)上tl.set(conn);}return conn;}public static Connection getConnection() throws SQLException {return dataSource.getConnection();}//回滚事务public static void rollback() throws SQLException {// TODO Auto-generated method stubgetCurrentConnection().rollback();}//提交事务public static void commit() throws SQLException {// TODO Auto-generated method stubConnection conn=getCurrentConnection();conn.commit();//将Connection从ThreadLocal中移除tl.remove();conn.close();}}

TransferDao2.java

package cn.ctgu.dao;import java.sql.Connection;
import java.sql.SQLException;import org.apache.commons.dbutils.QueryRunner;public class TransferDao2 {public void out(String out,double money) throws SQLException {QueryRunner qr=new QueryRunner();Connection conn=MyDataSourceUtils.getCurrentConnection();Object[]params= {money,out};String sql= "UPDATE counts SET money=money-? WHERE cname=?";qr.update(conn,sql,params);}public void in(String in,double money) throws SQLException {QueryRunner qr=new QueryRunner();Connection conn=MyDataSourceUtils.getCurrentConnection();Object[]params= {money,in};String sql="UPDATE counts SET money=money+? WHERE cname=?";qr.update(conn,sql,params);}
}

JavaWeb——数据库(Mysql)相关推荐

  1. SEEK学习论坛-JavaWeb开发实训课题 (数据库MySQL+js+Ajax+Servlet)

    关于这次学校实训,我们做了一个类似于CSDN博客的项目,然后我们小组取名叫SEEK,一个学习论坛,前面ppt有介绍,我主要是负责后端数据库的,与MySQL交互,由我的组长写好js代码,然后将前端所获取 ...

  2. JavaWeb连接MySQL数据库最细图解

    JavaWeb连接MySQL数据库的方式有很多,首先我们讲解JDBC的配置方法 一.JDBC的配置方法 1.什么是JDBC 什么是JDBC嘞?JDBC代表Java数据库连接(Java Database ...

  3. JavaWeb笔记——MySQL数据库

    1.数据库介绍 数据库相关概念 在这一部分,我们先来讲解三个概念:数据库.数据库管理系统.SQL. 数据库是一种数据管理软件系统. 全称:DBMS--数据库管理系. 数据库 所以我们需要独立的.专用的 ...

  4. JavaWeb - 数据库,MySQL安装卸载,MySQL服务器存储结构,sql语言,使用sql操作数据库/数据库表/表中记录,聚集函数,分组操作,limit关键字,重置root密码

    转载请注明出处:https://blog.csdn.net/mythmayor/article/details/72781451 1.数据库的简介 (1)什么是数据库,就是一个文件系统,使用标准sql ...

  5. javaweb数据库操作

    本文主要内容有C3P0数据库连接池,dbutils的使用,元数据的应用 在对数据库进行增删改查时,使用数据库连接池可以有效的提高效率,节省资源,C3P0是Apache组织提供的一个有效方式 C3P0的 ...

  6. 基于javaweb+jsp的个人日记管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Bootstrap Ajax)

    基于javaweb+jsp的个人日记管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Bootstrap Ajax) 运行环境 Java≥8.MySQL≥5. ...

  7. 基于javaweb+jsp的大学生个人财务记账系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Bootstrap)

    基于javaweb+jsp的大学生个人财务记账系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Bootstrap) 运行环境 Java≥8.MySQL≥5.7. ...

  8. 基于javaweb+jsp的校园快递管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Bootstrap Ajax)

    基于javaweb+jsp的校园快递管理系统(JavaWeb JSP MySQL Servlet SSM SpringBoot Bootstrap Ajax) JavaWeb JavaBean JSP ...

  9. JavaWeb数据库学生宿舍图书管理系统+地图

    原文链接:JavaWeb数据库学生宿舍图书管理系统+地图 登陆之后现实主页面,账号密码储存在数据库中. 实现对数据库的增删改查 java 9.0.4 + mysql 8.0.19 + Navicat ...

  10. linux笔记本没有insert,无法在Linux中将UTF8插入数据库MySQL(Can not insert UTF8 to Database MySQL in Linux)...

    无法在Linux中将UTF8插入数据库MySQL(Can not insert UTF8 to Database MySQL in Linux) 当创建表时,我已经设置了charset = utf8. ...

最新文章

  1. lstm timestep一般是多少_请问rnn和lstm中batchsize和timestep的区别是什么?
  2. 问题集锦(1-10)
  3. 将表数据生成Insert脚本
  4. js 函数定义的方式
  5. android 拷贝文件到其他目录下
  6. 【STC15库函数上手笔记】3、外部中断
  7. Java中<? super T>和List<? extends T>的区别
  8. ETL异构数据源Datax_使用querySql_08
  9. Apple Watch问与答
  10. 怎么实现单点登录?面试必问!
  11. 世界七大数学难题与Hilbert的23个问题
  12. 断点续传实现文件下载进度条
  13. stm32霍尔编码器电机测速原理
  14. python输入名字、输出_Python输入输出
  15. linux系统宝塔安装nodejs,基于debian宝塔面板安装nodebb – 一款基于Node.js的论坛程序...
  16. TCP/IP第二章笔记链路层协议
  17. Python 数据清理实战
  18. 算法岗的招聘现状与未来
  19. 将unix文本文件格式转换为windows文 本文件的格式
  20. 全球与中国1,6-己二醇二甲基丙烯酸酯(HDDMA)市场深度研究分析报告

热门文章

  1. xshow-2. 使用HTML 5 Boilerplate构建前端
  2. 遇到的问题要记录下来 javascript值班表
  3. VMwareWorkStation虚拟机安装RHEL7.0Linux操作系统
  4. 高等数学竞赛题解析教程P26 - 例1.52(浙江2008竞赛题)
  5. mysql查询权限show grants_[MySQL]查看用户权限与GRANT用法
  6. 数学分析常用的4款软件对比!
  7. 【JAVA多线程】如何解决一个生产者与消费者问题
  8. 麦肯锡 7S 诊断模型
  9. TU-ctf-2016 pwn woO 分析记录
  10. 使用Python PySNMP模块获取设备指标