最近一直在看数学跟英语,好久没碰电脑了。这次尝试用idea,并且破解了永久版本,使用起来,跟eclipse相比,太好用啦!
今天晚上竟然刷了半个多小时的吴京的采访视频,我也是醉咯!不过吴京这人还挺有意思。
先附上java中jar包的maven仓库的国内镜像下载地址,关于JDBC也发现了一个比较好的教程网站
一、了解JDBC
概念:Java DataBase Connectivity即java数据库连接,java语言操作数据库
本质:官方(Sun)公司定义的一套操作所有关系型数据库的规则,即接口。然后各个数据库厂商去实现这套接口,提供数据库驱动jar包,开发者可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
二、入门JDBC
下面这就是上课时我们所用到的代码,拿来就用。具体为什么要这么用,我也不知道,老师也说不用知道,都是这个套路。
google一下,发现网上的教程,比老师讲得清楚明了
步骤
- 导入驱动jar包
- 注册驱动
- 获取数据库连接对象(Connection)
- 定义sql
- 获取执行sql语句的对象(Statement)
- 执行sql,接收返回的结果
- 处理结果
- 释放资源
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class Demo01JDBC { public static void main(String[] args) throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/beauty?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false","root","13838385638"); String sql="select * from memeber"; Statement stmt=conn.createStatement(); ResultSet rs=stmt.executeQuery(sql); while(rs.next()) { String name=rs.getString("name"); String gender=rs.getString("gender"); System.out.println(name+"->"+gender); } stmt.close(); conn.close(); } }
|
三、详解JDBC
3.1 DriverManager:驱动管理对象
功能
- 注册驱动
- 获取数据库连接
注册驱动
注册驱动:告诉程序使用哪一个数据库驱动jar,讲解
在DriverManager里面,有这样一个方法
1 2
| static void registerDriver (Driver driver)
|
Class.forName(“全类名”),在源代码阶段,将字节码文件加载进内存,并返回类对象,当然,这个是没有接收的。
通过查看源码,发现在com.mysql.cj.jdbc.Driver
类中,调用了静态代码块
1 2 3 4 5 6 7
| static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
|
mysql5之后的版本可以省略注册驱动
也就是说,我们其实可以直接使用DriverManager.registerDriver(new Driver())
来代替Class.forName("xxx")
;
获取数据库连接对象
在DriverManager里面有这样一个方法
1 2 3 4 5 6 7 8 9 10
|
public static Connection getConnection(String url, String user, String password)
|
3.2 Connection:数据库连接对象
功能
- 获取执行sql的对象
- 管理事务
获取执行sql的对象
Connection中有两个这样的方法
1 2 3 4
| Statement createStatement();
PreparedStatement prepareStatement(String sql);
|
管理事务
开启事务
1 2
| void setAutoCommit(boolean autoCommit);
|
提交事务
回滚事务
3.3 Statement:执行sql对象
执行sql
1 2 3 4 5 6 7 8 9
|
boolean execute(String sql);
int executeUpdate(String sql);
ResultSet executeQuery(String sql);
|
练习
添加记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| public class Demo02JDBC { public static void main(String[] args) { Connection conn=null; Statement stmt=null; try { Class.forName("com.mysql.cj.jdbc.Driver"); String sql="insert into memeber(name,gender,age,grade,p_id) values('武当陈师行','男',40,100,1)"; conn=DriverManager.getConnection("jdbc:mysql:///beauty?serverTimezone=Asia/Shanghai", "root", "13838385638"); stmt=conn.createStatement(); int count=stmt.executeUpdate(sql); if(count>0) { System.out.println("添加成功"); }else { System.out.println("添加失败"); } stmt.close(); conn.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
|
修改记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class Demo03JDBC { public static void main(String[] args) { Connection conn=null; Statement stmt=null; try { Class.forName("com.mysql.cj.jdbc.Driver"); conn=DriverManager.getConnection("jdbc:mysql:///beauty?serverTimezone=Asia/Shanghai", "root", "13838385638"); String sql="update memeber set grade=99 where id=2"; stmt=conn.createStatement(); int count=stmt.executeUpdate(sql); if(count>0) { System.out.println("修改成功"); }else { System.out.println("修改失败"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
|
删除记录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class Demo04JDBC { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); String sql = "delete from memeber where name='武当陈师行'"; conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/beauty?serverTimezone=Asia/Shanghai", "root", "13838385638"); stmt = conn.createStatement(); int count = stmt.executeUpdate(sql); if (count > 0) { System.out.println("删除成功"); } else { System.out.println("删除失败"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
|
3.4 ResultSet:结果集
使用
- next():游标向下移动一行,并返回boolean类型值。向下移动,若有数据,则是true,否则为false
- getxxx(参数):获取数据。
- xxx代表数据类型。
- 参数可以接收int,表示列的编号,从1开始,不是0,特殊。
- 参数可以接受String,表示列名称。
使用步骤:
- 游标向下移动一行
- 判断是否有数据
- 获取数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class Demo05JDBC { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); String sql = "select * from memeber"; conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/beauty?serverTimezone=Asia/Shanghai", "root", "13838385638"); stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) { System.out.println(rs.getString("name") + " " + rs.getString("gender")); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
|
查询练习
定义一个方法,查询emp表的数据,将其封装为对象,装载集合,返回
初版本
Emp.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
public class Emp { private int id; private String ename; private int job_id; private int mgr; private Date joindate; private double salary; private double bonus; private int dept_id; public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getEname() { return ename; }
public void setEname(String ename) { this.ename = ename; }
public int getJob_id() { return job_id; }
public void setJob_id(int job_id) { this.job_id = job_id; }
public int getMgr() { return mgr; }
public void setMgr(int mgr) { this.mgr = mgr; }
public Date getJoindate() { return joindate; }
public void setJoindate(Date joindate) { this.joindate = joindate; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public double getBonus() { return bonus; }
public void setBonus(double bonus) { this.bonus = bonus; }
public int getDept_id() { return dept_id; }
public void setDept_id(int dept_id) { this.dept_id = dept_id; }
@Override public String toString() { return "Emp {id=" + id + ", ename=" + ename + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + "}"; } }
|
Demo06JDBC.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| public class Demo06JDBC { public static void main(String[] args) { List<Emp> list=new Demo06JDBC().findAll(); System.out.println(list); }
public List<Emp> findAll() { List<Emp> list = null; Connection conn = null; Statement stmt = null; ResultSet rs = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///beauty?serverTimezone=Asia/Shanghai", "root", "13838385638"); String sql = "select * from emp"; stmt = conn.createStatement(); rs = stmt.executeQuery(sql); Emp emp = null; list=new ArrayList<Emp>(); while (rs.next()) { int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); list.add(emp); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
return list; } }
|
优化版本
目的:简化书写
步骤:
- 抽取注册驱动
- 抽取一个方法来获取连接对象
- 需求:不传递参数,同时还要保证工具类的通用性
- 解决:配置文件,在之前的博客也有提到使用方法
- 抽取一个方法来释放资源
util.JDBCUtils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| public class JDBCUtils {
private static String url; private static String user; private static String password; private static String driver;
static { Properties pro = new Properties(); try {
ClassLoader loader = JDBCUtils.class.getClassLoader(); URL res = loader.getResource("jdbc.properties"); String path = res.getPath(); pro.load(new FileInputStream(path)); url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
}
public static Connection getConnection() throws SQLException { Connection conn = null; conn = DriverManager.getConnection(url, user, password);
return conn; }
public static void close(Statement stmt, Connection conn) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
public static void close(ResultSet rs, Statement stmt, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
|
jdbc.JDBC.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
public class JDBC { public static void main(String[] args) { List<Emp> list=new JDBC().findAll(); System.out.println(list); }
public List<Emp> findAll() { Connection conn=null; Statement stmt=null; ResultSet rs=null; Emp emp=null; List<Emp> list=null; try { conn=JDBCUtils.getConnection(); stmt=conn.createStatement(); String sql="select * from emp"; rs=stmt.executeQuery(sql); list=new ArrayList<Emp>(); while(rs.next()) { int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); list.add(emp); } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(rs, stmt, conn); } return list; } }
|
domain.Emp.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
public class Emp { private int id; private String ename; private int job_id; private int mgr; private Date joindate; private double salary; private double bonus; private int dept_id; public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getEname() { return ename; }
public void setEname(String ename) { this.ename = ename; }
public int getJob_id() { return job_id; }
public void setJob_id(int job_id) { this.job_id = job_id; }
public int getMgr() { return mgr; }
public void setMgr(int mgr) { this.mgr = mgr; }
public Date getJoindate() { return joindate; }
public void setJoindate(Date joindate) { this.joindate = joindate; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public double getBonus() { return bonus; }
public void setBonus(double bonus) { this.bonus = bonus; }
public int getDept_id() { return dept_id; }
public void setDept_id(int dept_id) { this.dept_id = dept_id; }
@Override public String toString() { return "Emp {id=" + id + ", ename=" + ename + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + "}"; } }
|
jdbc.properties
1 2 3 4
| url=jdbc:mysql:///beauty?serverTimezone=Asia/Shanghai user=root password=13838385638 driver=com.mysql.cj.jdbc.Driver
|
登录练习
需求:
- 通过键盘录入用户名和密码
- 判断用户是否登录成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public class Demo07JDBC { public static void main(String[] args) { Scanner input=new Scanner(System.in); String user=input.nextLine(); String password=input.nextLine(); if(login(user,password)) { System.out.println("登录成功"); }else { System.out.println("登录失败"); } input.close(); }
public static boolean login(String user,String password) { if(user==null||password==null) { return false; } Connection conn=null; Statement stmt=null; ResultSet rs=null; try { conn=JDBCUtils.getConnection(); String sql="select * from user where user='"+user+"' and password='"+password+"'"; stmt=conn.createStatement(); rs=stmt.executeQuery(sql); return rs.next(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs, stmt, conn); } return false; } }
|
但是,这样登录,会出现sql注入的问题。
假如,密码输入的是a’ or ‘a’ = ‘a,那么整个sql语句select * from user where user=’fjaljfl’ and password=’a’ or ‘a’ = ‘a’
不论怎么查,都会返回数据
3.5 PreparedStatement:执行sql的对象
- sql注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性的问题
- 解决sql注入问题:使用PreparedStatement对象来解决
静态sql:直接拼接而成的sql,这种会产生sql注入问题
预编译sql:参数使用?作为占位符
JDBC的步骤也会相应改变
- 导入驱动jar包
- 注册驱动
- 获取数据库连接对象(Connection)
- 定义sql,参数使用占位符
- select * from where user = ? and password = ?;
- 获取执行sql语句的对象(PreparedStatement)
- 给占位符赋值
- 方法:setXXX(参数1,参数2)
- 参数1:位置的编号。从1开始
- 参数2:值
- 执行sql,接收返回的结果
- 处理结果
- 释放资源
改造上面的登录案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class Demo08JDBC { public static void main(String[] args) { Scanner input=new Scanner(System.in); String user=input.nextLine(); String password=input.nextLine(); if(login(user,password)) { System.out.println("登录成功"); }else { System.out.println("登录失败"); } input.close(); }
public static boolean login(String user,String password) { if(user==null||password==null) { return false; } Connection conn=null; PreparedStatement pstmt=null; ResultSet rs=null; try { conn=JDBCUtils.getConnection(); String sql="select * from user where user= ? and password= ?"; pstmt=conn.prepareStatement(sql); pstmt.setString(1, user); pstmt.setString(2, password); rs=pstmt.executeQuery(); return rs.next(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(rs, pstmt, conn); } return false; } }
|
实际开发中经常使用PreparedStatement来完成增删改查操作
- 防止sql注入
- 效率更高
四、JDBC管理事务
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
操作
- 开启事务
- 提交事务
- 回滚事务
使用Connection对象来管理事务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public class Demo09JDBC { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null;
try { conn = JDBCUtils.getConnection(); conn.setAutoCommit(false); String sql1 = "update account set balance = balance-? where id=?"; String sql2 = "update account set balance = balance+? where id=?"; pstmt1=conn.prepareStatement(sql1); pstmt2=conn.prepareStatement(sql2); pstmt1.setDouble(1, 500); pstmt1.setInt(2, 1); pstmt2.setDouble(1, 500); pstmt2.setInt(2, 2); pstmt1.executeUpdate(); int i=3/0; pstmt2.executeUpdate(); conn.commit(); } catch (Exception e) { try { if(conn!=null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); } finally { JDBCUtils.close(pstmt1, conn); JDBCUtils.close(pstmt2, null); } } }
|
五、数据库连接池
概念:本质是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。
好处
- 节约资源
- 用户访问过程变得高效
实现
- 标准接口:DataSource,javax.sql包下的官方提供的接口
- 获取连接:getConnection()
- 归还连接:如果连接对象Connection是从连接池中获取的,那么调用Connection.close()则不会关闭连接,而是归还连接。
- 一般是由数据库厂商来实现,推荐三种数据库连接池技术
- C3P0:比较老
- Druid:由阿里巴巴提供的,而且高效。号称全球最好?!
- DBCP:apache上的java连接池项目,也是tomcat使用的连接池组件。
5.1 C3P0
在这之前,我要强烈吐槽eclipse!
我用的eclipse最新版2019.06,搞这个数据库连接池的时候,eclipse成功把我推向了idea。主要就是在新版jdk中,eclipse是读不到配置文件的,无论你放到哪里,他都读不到。但是如果把jdk降为1.8,就可以了。
同时,还有个坑,我如果一开始建的项目以jdk1.8为准,后期再换成jdk新版,哎,他又可以用了,玄学啊!如果一开始直接建以最新jdk的项目,他是不能导出jar包的,会无缘无故失败。但是换成1.8,再换成新版,又可以了,又是玄学啊!
而idea,不论是哪个版本jdk,都能完美运行,这就是收费跟不收费软件的区别吗?
发现这个问题的,还有一个小伙伴,他的博客
eclipse,我以后不会再用了。idea,他不香吗?
c3p0文档
c3p0配置文件
步骤
- 导入jar包 c3p0.jar跟mchange.jar
- 定义配置文件 c3p0.properties或者c3p0-config.xml,直接将文件放置到src下面即可
- 创建核心对象 数据库连接池对象 ComboPooledDataSource
- 获取连接 getConnection
实现
c3p0-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <c3p0-config> <default-config> <property name="user">root</property> <property name="password">13838385638</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/beauty?serverTimezone=Asia/Shanghai</property> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">5</property> <property name="checkoutTimeout">3000</property> </default-config> <named-config name="otherc3p0"> <property name="user">root</property> <property name="password">13838385638</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/beauty?serverTimezone=Asia/Shanghai</property> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="initialPoolSize">5</property> <property name="maxPoolSize">5</property> <property name="checkoutTimeout">3000</property> </named-config> </c3p0-config>
|
当然,也可以用c3p0.properties
1 2 3 4 5 6 7 8 9
| c3p0.driverClass=com.mysql.cj.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql://localhost:3306/beauty?serverTimezone=Asia/Shanghai c3p0.user=root c3p0.password=13838385638 c3p0.acquireIncrement=5 c3p0.initialPoolSize=20 c3p0.minPoolSize=10 c3p0.maxPoolSize=40 c3p0.checkoutTimeout=5000
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Demo01c3p0 { public static void main(String[] args) throws SQLException {
DataSource ds=new ComboPooledDataSource("otherc3p0"); Connection conn=ds.getConnection(); System.out.println(conn); System.out.println(); } }
|
5.2 Druid
步骤
- 导入jar包
- 定义配置文件.properties
- properties格式
- 任意名称,可以放在任意目录下
- 加载配置文件
- 获取数据库连接池对象:通过工厂类DruidDataSourceFactory,来获取
- 获取连接:getConnection
配置文件
1 2 3 4 5 6 7 8
| driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql:///beauty?serverTimezone=Asia/Shanghai username=root password=13838385638 initialSize=5 maxActive=10 maxWait=3000
|
代码
1 2 3 4 5 6 7 8 9 10 11 12
| public class Demo03Druid { public static void main(String[] args) throws Exception { Properties pro=new Properties(); pro.load(Demo03Druid.class.getClassLoader().getResourceAsStream("druid.properties")); DataSource ds = DruidDataSourceFactory.createDataSource(pro); Connection conn=ds.getConnection(); System.out.println(conn); } }
|
5.3 定义连接池工具类
步骤
- 定义类JDBCPoolUtils
- 提供静态代码块,来加载配置文件,并且初始化连接池对象
- 提供方法
- 获取连接方法:getConnection
- 释放资源:close()
- 获取连接池的方法:getDataSource
实现
JDBCPoolUtils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
public class JDBCPoolUtils { private static DataSource ds; static { Properties pro=new Properties(); try { pro.load(JDBCPoolUtils.class.getClassLoader().getResourceAsStream("druid.properties")); ds= DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }
public static Connection getConnection() throws SQLException { return ds.getConnection(); }
public static void close(ResultSet rs,Statement stmt, Connection conn){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
public static DataSource getDataSource(){ return ds; } }
|
DruidMain.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
public class DruidMain { public static void main(String[] args) { Connection conn = null; ResultSet rs = null; PreparedStatement pstmt = null; try { conn = JDBCPoolUtils.getConnection();
String sql="update memeber set gender=? where name=?"; pstmt=conn.prepareStatement(sql); pstmt.setString(1,"男"); pstmt.setString(2,"唐三"); int count=pstmt.executeUpdate(); System.out.println(count); if(count>0){ System.out.println("成功"); }else{ System.out.println("失败"); } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCPoolUtils.close(rs,pstmt,conn); } } }
|
六、Spring JDBC
Spring框架对JDBC的简单封装。提供了JDBCTemplate来简化JDBC的开发
上学期课程设计的时候,我就觉得这部分比较麻烦,问老师,老师也支支吾吾说不明白。老师大概也就只要个功能,具体的实现优化,他才不管,我猜,他也不会。
报告管理信息系统,说实话,写得很幼稚。
步骤
- 导入jar包 core.jar jdbc.jar tx.jar beans.jar commons-logging.jar
- 创建JDBCTemplate对象。依赖于数据源DataSource
- JDBCTemlate temp=new JDBCTemplate(ds);
- 调用方法来CRUD(增删改)操作
- update():执行DML语句。增删改
- queryForMap():查询结果,将结果集封装为Map。
- 列名作为key,值作为value,将这条记录封装为map集合。(长度只能为1)
- queryForList():查询结果,将将结果集封装为List。
- 将每一条Map封装为Map集合,再将Map集合装载到List集合中
- query():查询结果,将结果封装为javaBean对象
- query的参数:RowMapper。一般我们使用BeanPropertyRowMapper实现类,它可以完成数据到javaBean的自动封装
- 使用方法:new BeanPropertyRowMapper<类名>(类名.Class)
- queryForObject():查询结果,将结果封装为指定对象
- 一般用于聚合函数的查询。比方说返回的结果是Long类型,就需要将结果封装
1 2 3 4 5 6 7 8 9 10
| public class Demo01JDBCTemplate { public static void main(String[] args) { JdbcTemplate temp=new JdbcTemplate(JDBCPoolUtils.getDataSource()); String sql="update memeber set gender=? where name=?"; int count=temp.update(sql,"男","唐三"); System.out.println(count); } }
|
使用
需求
- 修改id为1数据salary为10000
- 添加一条记录
- 删除刚才添加的记录
- 查询id为1的记录,将其封装为Map集合
- 查询所有记录,封装为List集合
- 查询所有记录,封装为Emp对象的List集合
- 查询总记录数
实现
通过Junit单元测试来实现每个需求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
public class Demo02JDBCTemplate { private JdbcTemplate temp = new JdbcTemplate(JDBCPoolUtils.getDataSource());
@Test public void test1() { String sql = "update emp set salary=10000 where id=1001"; int count = temp.update(sql); if (count > 0) { System.out.println("成功"); } else { System.out.println("失败"); } }
@Test public void test2() { String sql = "insert into emp(id,ename,dept_id) values(?,?,?)"; int count = temp.update(sql, 1015, "胡列娜", 10); if (count > 0) { System.out.println("成功"); } else { System.out.println("失败"); } }
@Test public void test3() { String sql = "delete from emp where id=?"; int count = temp.update(sql, 1015); if (count > 0) { System.out.println("成功"); } else { System.out.println("失败"); } }
@Test public void test4() { String sql = "select * from emp where id=?"; Map<String, Object> map = temp.queryForMap(sql, 1001); System.out.println(map); }
@Test public void test5() { String sql = "select * from emp"; List<Map<String, Object>> list = temp.queryForList(sql); for (Map<String, Object> map : list) { System.out.println(map); } }
@Test public void test6() { String sql = "select * from emp"; List<Emp> list = temp.query(sql, new RowMapper<Emp>() { @Override public Emp mapRow(ResultSet rs, int i) throws SQLException { Emp emp = new Emp(); int id = rs.getInt("id"); String ename = rs.getString("ename"); int job_id = rs.getInt("job_id"); int mgr = rs.getInt("mgr"); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble("salary"); double bonus = rs.getDouble("bonus"); int dept_id = rs.getInt("dept_id"); emp.setId(id); emp.setEname(ename); emp.setBonus(bonus); emp.setDept_id(dept_id); emp.setJoindate(joindate); emp.setMgr(mgr); emp.setSalary(salary); emp.setJob_id(job_id); return emp; } }); for (Emp emp : list) { System.out.println(emp); } }
@Test public void test7() { String sql = "select * from emp";
List<Emp1> list = temp.query(sql, new BeanPropertyRowMapper<Emp1>(Emp1.class)); for (Emp1 emp : list) { System.out.println(emp); } }
@Test public void test8() { String sql = "select count(id) from emp"; Long total = temp.queryForObject(sql, Long.class); System.out.println(total); } }
|