JDBC数据库连接

1_JDBC概述

什么是JDBC 

JDBC(Java DataBase Connectivity,  Java数据库连接) ,是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成 

有了JDBC,程序员只需用JDBC API写一个程序,就可访问所有数据库。 

Sun公司、数据库厂商、程序员三方关系

SUN公司是规范制定者,制定了规范JDBC(连接数据库规范) 

DriverManager类   作用:管理各种不同的JDBC驱动

Connection接口  

Statement接口和PreparedStatement接口    

ResultSet接口

数据库厂商微软、甲骨文等分别提供实现JDBC接口的驱动jar包

程序员学习JDBC规范来应用这些jar包里的类。

JDBC访问数据库编码步骤

1:加载一个Driver驱动

2:创建数据库连接(Connection)

3:创建SQL命令发送器Statement

4:通过Statement发送SQL命令并得到结果

5:处理结果(select语句)

6:关闭数据库资源ResultSet  Statement  Connection

创建模块/项目 导入jar包

JDBD历史版本及特征 

JDBC 1.0

JDBC 1.0 随JDK1.1一起发布,JDBC操作相关的接口和类位于java.sql包中。

JDBC 2.0

JDBC 2.0 API被划分为两部分:核心API和扩展API,有两个包,分别是java.sql包和javax.sql包。

java.sql核心API包 

在支持新功能方面:包括结果集可以向后滚动,批量的更新数据。另外,还提供了UNICODE字符集的字符流操作。

在支持SQL的数据类型方面:新增加的BLOB, CLOB,和数组接口能够是应用程序操作大块的数据类型

javax.sql扩展API包 

DataSource数据源接口:

JDBC1.0是原来是用DriverManager类来产生一个对数据源的连接。JDBC2.0用一种替代的方法,使用DataSource的实现,代码变的更小巧精致,也更容易控制。

Connection pooling

如果DataSource对象实现与一个支持连接池的中间层的服务器一起工作,DataSource对象就会自动的返回连接池中的连接,这个连接也是可以重复利用的。

Distrubute transaction:

在一个事务中涉及到了多个数据库服务器。获得一个用来支持分布式事务的连接与获得连接池中的连接是很相似的。同样,不同之处在于DataSource的实现上的不同,而不是在应用程序中获得连接的方式上有什么不同。

Rowsets:

RowSet接口扩展了ResultSet接口。这样RowSet对象就有了ResultSet对象所有的功能。不可以滚动的ResultSet变成了可以滚动的RowSet。

2_JDBC初识

1创建项目和模块.将jar文件放入项目的lib目录中

2给当前项目添加依赖(告诉当前项目/模块可以依赖jar文件中的代码)

点击OK

向部门表中添加一条数据

  1. package com.msb.test1;
  2. import java.sql.Connection;
  3. import java.sql.Driver;
  4. import java.sql.DriverManager;
  5. import java.sql.Statement;
  6. /**
  7.  * @Author: Ma HaiYang
  8.  * @Description: MircoMessage:Mark_7001
  9.  */
  10. public class TestJDBC {
  11.     public static void main(String[] args) throws Exception {
  12.         /*
  13.         * 向Dept表增加一条数据
  14.         *
  15.         * */
  16.         //1加载驱动 Driver
  17.         Driver driver =new com.mysql.cj.jdbc.Driver();
  18.         //2注册驱动 DriverManager
  19.         DriverManager.registerDriver(driver);
  20.         //3获得链接 Connection
  21.         /*
  22.         *
  23.         * user:用户名
  24.         * password:密码
  25.         * url:统一资源定位符 定位我们要连接的数据库的
  26.         *   1协议         jdbc:mysql
  27.         *   2IP          127.0.0.1/localhost
  28.         *   3端口号       3306
  29.         *   4数据库名字   mydb
  30.         *   5参数
  31.         *   协议://ip:端口/资源路径?参数名=参数值&参数名=参数值&....
  32.         *   jdbc:mysql://127.0.0.1:3306/mydb
  33.         * */
  34.         String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
  35.         String user="root";
  36.         String password="root";
  37.         Connection connection =DriverManager.getConnection(url, user,password );
  38.         //4获得语句对象 Statment
  39.         Statement statement = connection.createStatement();
  40.         //5执行SQL语句,返回结果
  41.         /*
  42.         * insert delete update 操作都是调用statement.executeUpdate
  43.         * executeUpdate返回一个int值,代表数据库多少行数据发生了变化
  44.         * */
  45.         String sql="insert into dept values(50,'教学部','北京');";
  46.         int rows = statement.executeUpdate(sql);
  47.         System.out.println("影响数据行数为:"+rows);
  48.         //6释放资源
  49.         /*
  50.         * 注意顺序
  51.         * 后获得的先关闭,先获得的后关闭
  52.         * */
  53.         statement.close();
  54.         connection.close();
  55.     }
  56. }

 总结 

MySQL8中数据库连接的四个参数有两个发生了变化 

String driver = "com.mysql.cj.jdbc.Driver"; 

String url = "jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; 

或者String url = ".......serverTimezone=GMT%2B8"; 

错误1:Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc2.Driver 

原因:没有添加jar包或者com.mysql.jdbc2.Driver路径错误 

错误2:Exception in thread "main" java.sql.SQLException: 

No suitable driver found for jbdc:mysql://127.0.0.1:3306/stumgr 

原因:url错误 

错误3:Exception in thread "main" java.sql.SQLException: 

Access denied for user 'root'@'localhost' (using password: YES) 

原因:用户名或者密码错误 

  错误4:Exception in thread "main" com.mysql.jdbc.exceptions 

.jdbc4.MySQLIntegrityConstraintViolationException:Duplicate entry '90' for key 'PRIMARY'

原因:主键冲突 

错误5:Public Key Retrieval is not allowed 

如果用户使用 sha256_password 认证,密码在传输过程中必须使用 TLS 协议保护,但是如果 RSA 公钥不可用,可以使用服务器提供的公钥;可以在连接中通过 ServerRSAPublicKeyFile 指定服务器的 RSA 公钥,或者AllowPublicKeyRetrieval=True参数以允许客户端从服务器获取公钥;但是需要注意的是 AllowPublicKeyRetrieval=True可能会导致恶意的代理通过中间人攻击(MITM)获取到明文密码,所以默认是关闭的,必须显式开启 

在jdbc连接添加上参数allowPublicKeyRetrieval=true即可,注意参数间用&

驱动的加载 

加载数据库驱动时,我们可以通过自己创建一个实例的方式,然后去注册驱动 

在查看Driver的源代码时我们发现,该类内部有一个静态代码块,在代码块中就是在实例化一个驱动并在驱动中心注册.静态代码块会在类进入内存时执行,也就是说,我们只要让该类字节码进入内存,就会自动完成注册,不需要我们手动去new 

所以我们在代码中直接使用反射,通过Class.forName("com.mysql.jdbc.Driver"),加载该类进入内存即可 

我们继续查看jar包发现,jar包中已经默认配置了驱动类的加载 

jar--META-INF--services--java.sql.Driver--com.mysql.jdbc.Driver,在加载jar包时,会自动读取该内容并加载驱动,所以我们不去编写Class.forName("com.mysql.jdbc.Driver"),程序也是可以自动完成加载驱动的 

结合异常处理代码 

  1. package com.msb.test1;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. /**
  7.  * @Author: Ma HaiYang
  8.  * @Description: MircoMessage:Mark_7001
  9.  */
  10. public class TestJDBC3 {
  11.     private static String driver ="com.mysql.cj.jdbc.Driver";
  12.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  13.     private static String user="root";
  14.     private static String password="root";
  15.     public static void main(String[] args)  {
  16.         Connection connection=null;
  17.         Statement statement=null;
  18.         try{
  19.             Class.forName(driver);
  20.             connection =DriverManager.getConnection(url, user,password);
  21.             statement = connection.createStatement();
  22.             String sql="insert into dept values(DEFAULT ,'助教部门','北京');";
  23.             int rows = statement.executeUpdate(sql);
  24.             System.out.println("影响数据行数为:"+rows);
  25.         }catch (Exception e){
  26.             e.printStackTrace();
  27.         }finally {
  28.             if(null != statement){
  29.                 try {
  30.                     statement.close();
  31.                 } catch (SQLException e) {
  32.                     e.printStackTrace();
  33.                 }
  34.             }
  35.             if(null != connection){
  36.                 try {
  37.                     connection.close();
  38.                 } catch (SQLException e) {
  39.                     e.printStackTrace();
  40.                 }
  41.             }
  42.         }
  43.     }
  44. }

3_JDBC完成CURD

删除和修改部门信息

  1. package com.msb.test1;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.SQLException;
  5. import java.sql.Statement;
  6. /**
  7.  * @Author: Ma HaiYang
  8.  * @Description: MircoMessage:Mark_7001
  9.  */
  10. public class TestJDBC4 {
  11.     private static String driver ="com.mysql.cj.jdbc.Driver";
  12.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  13.     private static String user="root";
  14.     private static String password="root";
  15.     public static void main(String[] args)  {
  16.         //testDelete();
  17.         testUpdate();
  18.     }
  19.     public static void testUpdate(){
  20.         Connection connection=null;
  21.         Statement statement=null;
  22.         try{
  23.             Class.forName(driver);
  24.             connection =DriverManager.getConnection(url, user,password);
  25.             statement = connection.createStatement();
  26.             String sql="update dept set dname='总部',loc='北京' where deptno= 30 ";
  27.             int rows = statement.executeUpdate(sql);
  28.             System.out.println("影响数据行数为:"+rows);
  29.         }catch (Exception e){
  30.             e.printStackTrace();
  31.         }finally {
  32.             if(null != statement){
  33.                 try {
  34.                     statement.close();
  35.                 } catch (SQLException e) {
  36.                     e.printStackTrace();
  37.                 }
  38.             }
  39.             if(null != connection){
  40.                 try {
  41.                     connection.close();
  42.                 } catch (SQLException e) {
  43.                     e.printStackTrace();
  44.                 }
  45.             }
  46.         }
  47.     }
  48.     public static void testDelete(){
  49.         Connection connection=null;
  50.         Statement statement=null;
  51.         try{
  52.             Class.forName(driver);
  53.             connection =DriverManager.getConnection(url, user,password);
  54.             statement = connection.createStatement();
  55.             String sql="delete from dept where deptno =40";
  56.             int rows = statement.executeUpdate(sql);
  57.             System.out.println("影响数据行数为:"+rows);
  58.         }catch (Exception e){
  59.             e.printStackTrace();
  60.         }finally {
  61.             if(null != statement){
  62.                 try {
  63.                     statement.close();
  64.                 } catch (SQLException e) {
  65.                     e.printStackTrace();
  66.                 }
  67.             }
  68.             if(null != connection){
  69.                 try {
  70.                     connection.close();
  71.                 } catch (SQLException e) {
  72.                     e.printStackTrace();
  73.                 }
  74.             }
  75.         }
  76.     }
  77. }

需求:查询全部 员工信息 

  1. package com.msb.test1;
  2. import java.sql.*;
  3. /**
  4.  * @Author: Ma HaiYang
  5.  * @Description: MircoMessage:Mark_7001
  6.  */
  7. public class TestJDBC5 {
  8.     private static String driver ="com.mysql.cj.jdbc.Driver";
  9.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  10.     private static String user="root";
  11.     private static String password="root";
  12.     public static void main(String[] args)  {
  13.         testQuery();
  14.     }
  15.     public static void testQuery(){
  16.         Connection connection = null;
  17.         Statement statement=null;
  18.         ResultSet resultSet=null;
  19.         try{
  20.             Class.forName(driver);
  21.             connection = DriverManager.getConnection(url, user,password);
  22.             statement = connection.createStatement();
  23.             String sql="select * from emp";
  24.             resultSet = statement.executeQuery(sql);
  25.             while(resultSet.next()){
  26.                 int empno = resultSet.getInt("empno");
  27.                 String ename = resultSet.getString("ename");
  28.                 String job = resultSet.getString("job");
  29.                 int mgr = resultSet.getInt("mgr");
  30.                 Date hiredate = resultSet.getDate("hiredate");
  31.                 double sal= resultSet.getDouble("sal");
  32.                 double comm= resultSet.getDouble("comm");
  33.                 int deptno= resultSet.getInt("deptno");
  34.                 System.out.println(""+empno+" "+ename+" "+job+" "+mgr+" "+hiredate+" "+sal+" "+comm+" "+deptno);
  35.             }
  36.         }catch (Exception e){
  37.             e.printStackTrace();
  38.         }finally {
  39.             if(null != resultSet){
  40.                 try {
  41.                     resultSet.close();
  42.                 } catch (SQLException e) {e.printStackTrace();
  43.                 }
  44.             }
  45.             if(null != statement){
  46.                 try {
  47.                     statement.close();
  48.                 } catch (SQLException e) {
  49.                     e.printStackTrace();
  50.                 }
  51.             }
  52.             if(null != connection){
  53.                 try {
  54.                     connection.close();
  55.                 } catch (SQLException e) {
  56.                     e.printStackTrace();
  57.                 }
  58.             }
  59.         }
  60.     }
  61. }

 ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。

•       ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行。

•       初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后指向最后一条记录的后面。

方法名 

说    明 

boolean   next() 

将光标从当前位置向下移动一行 

boolean   previous() 

游标从当前位置向上移动一行 

void   close() 

关闭ResultSet 对象 

int   getInt(int colIndex) 

以int形式获取结果集当前行指定列号值 

int   getInt(String colLabel) 

以int形式获取结果集当前行指定列名值 

float   getFloat(int colIndex) 

以float形式获取结果集当前行指定列号值 

Float   getFloat(String colLabel) 

以float形式获取结果集当前行指定列名值 

String   getString(int colIndex)

以String 形式获取结果集当前行指定列号值 

StringgetString(String   colLabel) 

以String形式获取结果集当前行指定列名值 

作为一种好的编程风格,应在不需要Statement对象和Connection对象时显式地关闭它们。关闭Statement对象和Connection对象的语法形式为:用户不必关闭ResultSet。当它的 Statement 关闭、重新执行或用于从多结果序列中获取下一个结果时,该ResultSet将被自动关闭。

为什么将结果封装成对象或者对象集合? 

1java是面向对象的编程语言,java中所有的数据处理都是基于面向对象的编码风格实现的,让数据以符合java风格的形式存在,便于对数据的后续处理 

2ResultSet 集合虽然可以存放数据,但是它是JDBC中查询数据的一种手段,是一种数据的临时存储方案,使用完毕是要进行释放和关闭 

  

封装后台查询数据并在前台显示 

何将结果集中的数据在java中进行存储和传递? 

准备和数据库表格相对应的一个实体类,用于封装结果集中的每一条数据,数据库表格中的每一个字段就是实体类的一个属性,实体类的一个对象就可以用于存储数据库表中的一条记录. 

准备实体类

  1. package com.msb.entity;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. /**
  5.  * @Author: Ma HaiYang
  6.  * @Description: MircoMessage:Mark_7001
  7.  */
  8. /*
  9. * 实体类:
  10. * 和数据库表格名称和字段是一一对应的类
  11. * 该类的对象主要用处是存储从数据库中查询出来的数据
  12. * 除此之外,该类没有任何的其他功能
  13. * 要求
  14. * 1类名和表名保持一致  (见名知意)
  15. * 2属性个数和数据库的表的列数保持一致
  16. * 3属性的数据类型和列的数据类型保持一致
  17. * 4属性名和数据库表格的列名要保持一致
  18. * 5所有的属性必须都是私有的 (出于安全考虑)
  19. * 6实体类的属性推荐写成包装类
  20. * 7日期类型推荐写成java.util.Date
  21. * 8所有的属性都要有get和set方法
  22. * 9必须具备空参构造方法
  23. * 10实体类应当实现序列化接口 (mybatis缓存  分布式需要 )
  24. * 11实体类中其他构造方法可选
  25. * */
  26. public class Emp implements Serializable {
  27.     private Integer empno;
  28.     private String ename;
  29.     private String job;
  30.     private Integer mgr;
  31.     private Date hiredate;
  32.     private Double sal;
  33.     private Double comm;
  34.     private Integer deptno;
  35.     @Override
  36.     public String toString() {
  37.         return "Emp{" +
  38.                 "empno=" + empno +
  39.                 ", ename='" + ename + '\'' +
  40.                 ", job='" + job + '\'' +
  41.                 ", mgr=" + mgr +
  42.                 ", hiredate=" + hiredate +
  43.                 ", sal=" + sal +
  44.                 ", comm=" + comm +
  45.                 ", deptno=" + deptno +
  46.                 '}';
  47.     }
  48.     public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double comm, Integer deptno) {
  49.         this.empno = empno;
  50.         this.ename = ename;
  51.         this.job = job;
  52.         this.mgr = mgr;
  53.         this.hiredate = hiredate;
  54.         this.sal = sal;
  55.         this.comm = comm;
  56.         this.deptno = deptno;
  57.     }
  58.     public Emp(){
  59.     }
  60.     public Integer getEmpno() {
  61.         return empno;
  62.     }
  63.     public void setEmpno(Integer empno) {
  64.         this.empno = empno;
  65.     }
  66.     public String getEname() {
  67.         return ename;
  68.     }
  69.     public void setEname(String ename) {
  70.         this.ename = ename;
  71.     }
  72.     public String getJob() {
  73.         return job;
  74.     }
  75.     public void setJob(String job) {
  76.         this.job = job;
  77.     }
  78.     public Integer getMgr() {
  79.         return mgr;
  80.     }
  81.     public void setMgr(Integer mgr) {
  82.         this.mgr = mgr;
  83.     }
  84.     public Date getHiredate() {
  85.         return hiredate;
  86.     }
  87.     public void setHiredate(Date hiredate) {
  88.         this.hiredate = hiredate;
  89.     }
  90.     public Double getSal() {
  91.         return sal;
  92.     }
  93.     public void setSal(Double sal) {
  94.         this.sal = sal;
  95.     }
  96.     public Double getComm() {
  97.         return comm;
  98.     }
  99.     public void setComm(Double comm) {
  100.         this.comm = comm;
  101.     }
  102.     public Integer getDeptno() {
  103.         return deptno;
  104.     }
  105.     public void setDeptno(Integer deptno) {
  106.         this.deptno = deptno;
  107.     }
  108. }

使用实体类封装结果集

  1. package com.msb.test1;
  2. import com.msb.entity.Emp;
  3. import java.sql.*;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. /**
  7.  * @Author: Ma HaiYang
  8.  * @Description: MircoMessage:Mark_7001
  9.  */
  10. public class TestJDBC5 {
  11.     private static String driver ="com.mysql.cj.jdbc.Driver";
  12.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  13.     private static String user="root";
  14.     private static String password="root";
  15.     public static void main(String[] args)  {
  16.         List<Emp> emps = testQuery();
  17.         // 遍历集合
  18.         for (Emp emp : emps) {
  19.             System.out.println(emp);
  20.         }
  21.     }
  22.     public  static List<Emp>  testQuery(){
  23.         Connection connection = null;
  24.         Statement statement=null;
  25.         ResultSet resultSet=null;
  26.         List<Emp> list =null;
  27.         try{
  28.             Class.forName(driver);
  29.             connection = DriverManager.getConnection(url, user,password);
  30.             statement = connection.createStatement();
  31.             String sql="select * from emp";
  32.             resultSet = statement.executeQuery(sql);
  33.             list=new ArrayList<>();
  34.             while(resultSet.next()){
  35.                 int empno = resultSet.getInt("empno");
  36.                 String ename = resultSet.getString("ename");
  37.                 String job = resultSet.getString("job");
  38.                 int mgr = resultSet.getInt("mgr");
  39.                 Date hiredate = resultSet.getDate("hiredate");
  40.                 double sal= resultSet.getDouble("sal");
  41.                 double comm= resultSet.getDouble("comm");
  42.                 int deptno= resultSet.getInt("deptno");
  43.                 Emp emp =new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
  44.                 list.add(emp);
  45.             }
  46.         }catch (Exception e){
  47.             e.printStackTrace();
  48.         }finally {
  49.             if(null != resultSet){
  50.                 try {
  51.                     resultSet.close();
  52.                 } catch (SQLException e) {e.printStackTrace();
  53.                 }
  54.             }
  55.             if(null != statement){
  56.                 try {
  57.                     statement.close();
  58.                 } catch (SQLException e) {
  59.                     e.printStackTrace();
  60.                 }
  61.             }
  62.             if(null != connection){
  63.                 try {
  64.                     connection.close();
  65.                 } catch (SQLException e) {
  66.                     e.printStackTrace();
  67.                 }
  68.             }
  69.         }
  70.         return list;
  71.     }
  72. }
_SQL注入攻击
Sql注入

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。 

以模拟登录为例:在前台输入用户名和密码,后台判断信息是否正确,并给出前台反馈信息,前台输出反馈信息。 

具体实现步骤为 

 创建数据库表

创建实体类

public class Account implements Serializable {
    private int aid;
    private String username;
    private String password;
    private int money; 

测试代码

  1. package com.msb.test2;
  2. import com.msb.entity.Account;
  3. import com.msb.entity.Emp;
  4. import java.sql.*;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.Scanner;
  8. /**
  9.  * @Author: Ma HaiYang
  10.  * @Description: MircoMessage:Mark_7001
  11.  */
  12. public class TestInjection {
  13.     private static String driver ="com.mysql.cj.jdbc.Driver";
  14.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  15.     private static String user="root";
  16.     private static String password="root";
  17.     public static void main(String[] args) {
  18.         Scanner sc =new Scanner(System.in);
  19.         System.out.println("请输入用户名");
  20.         String username=sc.next();
  21.         System.out.println("请输入密码");
  22.         String pwd =sc.next();
  23.         Account account = getAccount(username, pwd);
  24.         System.out.println(null!= account?"登录成功":"登录失败");
  25.         sc.close();
  26.     }
  27.     public static Account getAccount(String username,String pwd){
  28.         Connection connection = null;
  29.         Statement statement=null;
  30.         ResultSet resultSet=null;
  31.         Account account =null;
  32.         try{
  33.             Class.forName(driver);
  34.             connection = DriverManager.getConnection(url, user,password);
  35.             statement = connection.createStatement();
  36.             String sql="select * from account where username ='"+username+"' and password ='"+pwd+"'";
  37.             System.out.println(sql);
  38.             resultSet = statement.executeQuery(sql);
  39.             while(resultSet.next()){
  40.                 int aid = resultSet.getInt("aid");
  41.                 String usernamea = resultSet.getString("username");
  42.                 String pwda = resultSet.getString("password");
  43.                 double money = resultSet.getDouble("money");
  44.                 account=new Account(aid,usernamea,pwda,money);
  45.                 System.out.println(account);
  46.             }
  47.         }catch (Exception e){
  48.             e.printStackTrace();
  49.         }finally {
  50.             if(null != resultSet){
  51.                 try {
  52.                     resultSet.close();
  53.                 } catch (SQLException e) {e.printStackTrace();
  54.                 }
  55.             }
  56.             if(null != statement){
  57.                 try {
  58.                     statement.close();
  59.                 } catch (SQLException e) {
  60.                     e.printStackTrace();
  61.                 }
  62.             }
  63.             if(null != connection){
  64.                 try {
  65.                     connection.close();
  66.                 } catch (SQLException e) {
  67.                     e.printStackTrace();
  68.                 }
  69.             }
  70.         }
  71.         return account;
  72.     }
  73. }

测试结果为: 

当输入了精心设计的用户名密码后,即使是错误的,也能登录成功。让登录功能形同虚设。这是为什么呢,这就是SQL注入风险,原因在于SQL语句是字符串拼接的。SQL语句中拼接的内容破坏了SQL语句原有的判断逻辑 

如何解决呢?使用PreparedStatement预编译语句对象就可以解决掉。 

5_预编译语句对象

     使用预编译语句对象防止注入攻击

  1. package com.msb.test2;
  2. import com.msb.entity.Account;
  3. import java.sql.*;
  4. import java.util.Scanner;
  5. /**
  6.  * @Author: Ma HaiYang
  7.  * @Description: MircoMessage:Mark_7001
  8.  */
  9. public class TestInjection2 {
  10.     private static String driver ="com.mysql.cj.jdbc.Driver";
  11.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  12.     private static String user="root";
  13.     private static String password="root";
  14.     public static void main(String[] args) {
  15.         Scanner sc =new Scanner(System.in);
  16.         System.out.println("请输入用户名");
  17.         String username=sc.next();
  18.         System.out.println("请输入密码");
  19.         String pwd =sc.next();
  20.         Account account = getAccount(username, pwd);
  21.         System.out.println(null!= account?"登录成功":"登录失败");
  22.         sc.close();
  23.     }
  24.     public static Account getAccount(String username,String pwd){
  25.         Connection connection = null;
  26.         PreparedStatement preparedStatement=null;
  27.         ResultSet resultSet=null;
  28.         Account account =null;
  29.         try{
  30.             Class.forName(driver);
  31.             connection = DriverManager.getConnection(url, user,password);
  32.             /*
  33.             * 1使用PreparedStatement语句对象防止注入攻击
  34.             * 2PreparedStatement 可以使用 ? 作为参数的占位符
  35.             * 3使用?作为占位符,即使是字符串和日期类型,也不使用单独再添加 ''
  36.             * 4connection.createStatement();获得的是普通语句对象 Statement
  37.             * 5connection.prepareStatement(sql);可以获得一个预编译语句对象PreparedStatement
  38.             * 6如果SQL语句中有?作为参数占位符号,那么要在执行CURD之前先设置参数
  39.             * 7通过set***(问号的编号,数据) 方法设置参数
  40.             * */
  41.             String sql="select * from account where username = ? and password = ?";
  42.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  43.             //设置参数
  44.             preparedStatement.setString(1,username );
  45.             preparedStatement.setString(2,pwd );
  46.             //执行CURD
  47.             resultSet = preparedStatement.executeQuery();// 这里不需要再传入SQL语句
  48.             while(resultSet.next()){
  49.                 int aid = resultSet.getInt("aid");
  50.                 String usernamea = resultSet.getString("username");
  51.                 String pwda = resultSet.getString("password");
  52.                 double money = resultSet.getDouble("money");
  53.                 account=new Account(aid,usernamea,pwda,money);
  54.                 System.out.println(account);
  55.             }
  56.         }catch (Exception e){
  57.             e.printStackTrace();
  58.         }finally {
  59.             if(null != resultSet){
  60.                 try {
  61.                     resultSet.close();
  62.                 } catch (SQLException e) {e.printStackTrace();
  63.                 }
  64.             }
  65.             if(null != preparedStatement){
  66.                 try {
  67.                     preparedStatement.close();
  68.                 } catch (SQLException e) {
  69.                     e.printStackTrace();
  70.                 }
  71.             }
  72.             if(null != connection){
  73.                 try {
  74.                     connection.close();
  75.                 } catch (SQLException e) {
  76.                     e.printStackTrace();
  77.                 }
  78.             }
  79.         }
  80.         return account;
  81.     }
  82. }

prepareStatment对象在set***方法上,会对单引号进行转译处理,也就是说,?中的数据的单引号  ‘  会被转义成 \’,这样就单引号就不会破坏sql语句的结构, 

SELECT *   FROM users WHERE  userName =  ?    AND password =  ? 

preparedStatement.setString(1,"xiaoming"); 

preparedStatement.setString(2,'anything'   OR 'x'='x'); 

会被转义为 

SELECT *   FROM users WHERE  userName = 'xiaoming'   AND password =  'anything\'   OR\'x\'=\'x\'' 

而不是 

SELECT *   FROM users WHERE  userName =  'xiaoming' AND password =  'anything' OR 'x'='x' 

  

说白了就是把值当中的所有单引号给转义了!这就达到了防止sql注入的目的,说白了mysql驱动的PreparedStatement实现类的setString();方法内部做了单引号的转义,而Statement不能防止sql注入,就是因为它没有把单引号做转义,而是简单粗暴的直接拼接字符串,所以达不到防止sql注入的目的。 

预编译

当客户端发送一条sql语句给DBMS时,MySQL的执行流程如下图

sql命令的执行流程如下 

1. 客户端向服务器端发送SQL命令

2. 服务器端连接模块连接并验证

3. 缓存模块解析SQL为Hash并与缓存中Hash表对应。如果有结果直接返回结果,如果没有对应继续向下执行

4. 解析器解析SQL为解析树,如果出现错误,报SQL解析错误。如果正确,向下传递

5. 预处理器对解析树继续处理,处理成新的解析树。

6. 优化器根据开销自动选择最优执行计划,生成执行计划

7. 执行器执行执行计划,访问存储引擎接口

8. 存储引擎访问物理文件并返回结果

9. 如果开启缓存,缓存管理器把结果放入到查询缓存中。

10. 返回结果给客户端

当客户发送一条SQL语句给DBMS后,DBMS总是需要校验SQL语句的语法格式是否正确,然后把SQL语句编译成可执行的函数,最后才是执行SQL语句。其中校验语法,和编译所花的时间可能比执行SQL语句花的时间还要多。 

预编译语句PreparedStatement 是java.sql中的一个接口,它是Statement的子接口。通过Statement对象执行SQL语句时,需要将SQL语句发送给DBMS,由DBMS首先进行编译后再执行。预编译语句和Statement不同,在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给DBMS进行编译。当该编译语句被执行时,DBMS直接运行编译后的SQL语句,而不需要像其他SQL语句那样首先将其编译。预编译的SQL语句处理性能稍微高于普通的传递变量的办法。 

例如:我们需要执行多次insert语句,但只是每次插入的值不同,MySQL服务器也是需要每次都去校验SQL语句的语法格式,以及编译,这就浪费了太多的时间。如果使用预编译功能,那么只对SQL语句进行一次语法校验和编译,所以效率要高。 

预编译如何开启? 

我们可以通过设置URL中的参数来控制预编译是否开启 

useServerPrepStmts是否开启预编译 

cachePrepStmts  是否启用预编译缓存 

"jdbc:mysql://localhost:3306/mydb?*****&useServerPrepStmts=true&cachePrepStmts=true";  

值得注意的是,我们的Connector/J 5.0.5及之后useServerPrepStmts默认false,就是默认没有开启预编译,之前默认为true, cachePrepStmts 一直默认为false,需要我们手动设置才可以启用预编译,在开启预编译的同时要同时开启预编译缓存才能带来些许的性能提升 

Statement和PreparedStatment的关系和区别 

关系:public interface PreparedStatement extends Statement 

区别 

PreparedStatment安全性高,可以避免SQL注入 

PreparedStatment简单不繁琐,不用进行字符串拼接 

PreparedStatment性能高,用在执行多个相同数据库DML操作时,可以减少sql语句的编译次数 

6_PrepareStatement完成CURD
  1. package com.msb.test3;
  2. import com.msb.entity.Emp;
  3. import java.sql.*;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. /**
  7.  * @Author: Ma HaiYang
  8.  * @Description: MircoMessage:Mark_7001
  9.  */
  10. public class TestPreparedSstatement {
  11.     private static String driver ="com.mysql.cj.jdbc.Driver";
  12.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  13.     private static String user="root";
  14.     private static String password="root";
  15.     public static void main(String[] args) {
  16.         //testAdd();
  17.         //testUpdate();
  18.         //testDelete();
  19.         testQuery();
  20.     }
  21.     public static void testAdd(){
  22.         // 向 Emp表中增加一条数据
  23.         Connection connection = null;
  24.         PreparedStatement preparedStatement=null;
  25.         try{
  26.             Class.forName(driver);
  27.             connection = DriverManager.getConnection(url, user,password);
  28.             String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)";
  29.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  30.             //设置参数
  31.             preparedStatement.setString(1,"Mark");
  32.             preparedStatement.setString(2,"MANAGER" );
  33.             preparedStatement.setInt(3,7839);
  34.             preparedStatement.setDate(4,new Date(System.currentTimeMillis()));
  35.             preparedStatement.setDouble(5,3000.12);
  36.             preparedStatement.setDouble(6,0.0);
  37.             preparedStatement.setDouble(7,30);
  38.             //执行CURD
  39.             int rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  40.             System.out.println(rows);
  41.         }catch (Exception e){
  42.             e.printStackTrace();
  43.         }finally {
  44.             if(null != preparedStatement){
  45.                 try {
  46.                     preparedStatement.close();
  47.                 } catch (SQLException e) {
  48.                     e.printStackTrace();
  49.                 }
  50.             }
  51.             if(null != connection){
  52.                 try {
  53.                     connection.close();
  54.                 } catch (SQLException e) {
  55.                     e.printStackTrace();
  56.                 }
  57.             }
  58.         }
  59.     }
  60.     public static void testUpdate(){
  61.         // 根据工号修改员工表中的数据
  62.         Connection connection = null;
  63.         PreparedStatement preparedStatement=null;
  64.         try{
  65.             Class.forName(driver);
  66.             connection = DriverManager.getConnection(url, user,password);
  67.             String sql="update emp set ename =? ,job=? where empno =?";
  68.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  69.             //设置参数
  70.             preparedStatement.setString(1,"Jhon");
  71.             preparedStatement.setString(2,"ANALYST" );
  72.             preparedStatement.setInt(3,7935);
  73.             //执行CURD
  74.             int rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  75.             System.out.println(rows);
  76.         }catch (Exception e){
  77.             e.printStackTrace();
  78.         }finally {
  79.             if(null != preparedStatement){
  80.                 try {
  81.                     preparedStatement.close();
  82.                 } catch (SQLException e) {
  83.                     e.printStackTrace();
  84.                 }
  85.             }
  86.             if(null != connection){
  87.                 try {
  88.                     connection.close();
  89.                 } catch (SQLException e) {
  90.                     e.printStackTrace();
  91.                 }
  92.             }
  93.         }
  94.     }
  95.     public static void testDelete(){
  96.         // 根据工号删除员工表中的数据
  97.         Connection connection = null;
  98.         PreparedStatement preparedStatement=null;
  99.         try{
  100.             Class.forName(driver);
  101.             connection = DriverManager.getConnection(url, user,password);
  102.             String sql="delete from emp where empno =?";
  103.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  104.             //设置参数
  105.             preparedStatement.setInt(1,7935);
  106.             //执行CURD
  107.             int rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  108.             System.out.println(rows);
  109.         }catch (Exception e){
  110.             e.printStackTrace();
  111.         }finally {
  112.             if(null != preparedStatement){
  113.                 try {
  114.                     preparedStatement.close();
  115.                 } catch (SQLException e) {
  116.                     e.printStackTrace();
  117.                 }
  118.             }
  119.             if(null != connection){
  120.                 try {
  121.                     connection.close();
  122.                 } catch (SQLException e) {
  123.                     e.printStackTrace();
  124.                 }
  125.             }
  126.         }
  127.     }
  128.     public static void testQuery(){
  129.         // 查询名字中包含字母A的员工信息
  130.         Connection connection = null;
  131.         PreparedStatement preparedStatement=null;
  132.         ResultSet resultSet=null;
  133.         List<Emp> list =null;
  134.         try{
  135.             Class.forName(driver);
  136.             connection = DriverManager.getConnection(url, user,password);
  137.             /*
  138.              * 1使用PreparedStatement语句对象防止注入攻击
  139.              * 2PreparedStatement 可以使用 ? 作为参数的占位符
  140.              * 3使用?作为占位符,即使是字符串和日期类型,也不使用单独再添加 ''
  141.              * 4connection.createStatement();获得的是普通语句对象 Statement
  142.              * 5connection.prepareStatement(sql);可以获得一个预编译语句对象PreparedStatement
  143.              * 6如果SQL语句中有?作为参数占位符号,那么要在执行CURD之前先设置参数
  144.              * 7通过set***(问号的编号,数据) 方法设置参数
  145.              * */
  146.             String sql="select * from emp where ename like ? ";
  147.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  148.             //设置参数
  149.             preparedStatement.setString(1,"%A%");
  150.             //执行CURD
  151.             resultSet = preparedStatement.executeQuery();// 这里不需要再传入SQL语句
  152.             list=new ArrayList<Emp>() ;
  153.             while(resultSet.next()){
  154.                 int empno = resultSet.getInt("empno");
  155.                 String ename = resultSet.getString("ename");
  156.                 String job = resultSet.getString("job");
  157.                 int mgr = resultSet.getInt("mgr");
  158.                 Date hiredate = resultSet.getDate("hiredate");
  159.                 double sal= resultSet.getDouble("sal");
  160.                 double comm= resultSet.getDouble("comm");
  161.                 int deptno= resultSet.getInt("deptno");
  162.                 Emp emp =new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
  163.                 list.add(emp);
  164.             }
  165.         }catch (Exception e){
  166.             e.printStackTrace();
  167.         }finally {
  168.             if(null != resultSet){
  169.                 try {
  170.                     resultSet.close();
  171.                 } catch (SQLException e) {
  172.                     e.printStackTrace();
  173.                 }
  174.             }
  175.             if(null != preparedStatement){
  176.                 try {
  177.                     preparedStatement.close();
  178.                 } catch (SQLException e) {
  179.                     e.printStackTrace();
  180.                 }
  181.             }
  182.             if(null != connection){
  183.                 try {
  184.                     connection.close();
  185.                 } catch (SQLException e) {
  186.                     e.printStackTrace();
  187.                 }
  188.             }
  189.         }
  190.         // 遍历集合
  191.         for (Emp emp : list) {
  192.             System.out.println(emp);
  193.         }
  194.     }
  195. }
7_批处理

 PreparedStatement批处理 

什么是批处理? 

当我们有多条sql语句需要发送到数据库执行的时候,有两种发送方式,一种是执行一条发送一条sql语句给数据库,另一个种是发送一个sql集合给数据库,也就是发送一个批sql到数据库。普通的执行过程是:每处理一条数据,就访问一次数据库;而批处理是:累积到一定数量,再一次性提交到数据库,减少了与数据库的交互次数,所以效率会大大提高,很显然两者的数据库执行效率是不同的,我们发送批处理sql的时候数据库执行效率要高 

statement语句对象实现批处理有如下问题
缺点:采用硬编码效率低,安全性较差。
原理:硬编码,每次执行时相似SQL都会进行编译  

  

PreparedStatement+批处理
优点:语句只编译一次,减少编译次数。提高了安全性(阻止了SQL注入)

原理:相似SQL只编译一次,减少编译次数

注意:  需要设置批处理开启&rewriteBatchedStatements=true

  1. package com.msb.test4;
  2. import java.sql.*;
  3. /**
  4.  * @Author: Ma HaiYang
  5.  * @Description: MircoMessage:Mark_7001
  6.  */
  7. public class TestBatch {
  8.     private static String driver ="com.mysql.cj.jdbc.Driver";
  9.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useServerPrepStmts=true&cachePrepStmts=true&&rewriteBatchedStatements=true";
  10.     private static String user="root";
  11.     private static String password="root";
  12.     public static void main(String[] args) {
  13.         testAddBatch();
  14.     }
  15.     // 定义一个方法,向部门表增加1000条数据
  16.     public static void testAddBatch(){
  17.         Connection connection = null;
  18.         PreparedStatement preparedStatement=null;
  19.         try{
  20.             Class.forName(driver);
  21.             connection = DriverManager.getConnection(url, user,password);
  22.             String sql="insert into dept values (DEFAULT ,?,?)";
  23.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  24.             //设置参数
  25.             for (int i = 1; i <= 10663; i++) {
  26.                 preparedStatement.setString(1, "name");
  27.                 preparedStatement.setString(2, "loc");
  28.                 preparedStatement.addBatch();// 将修改放入一个批次中
  29.                 if(i%1000==0){
  30.                     preparedStatement.executeBatch();
  31.                     preparedStatement.clearBatch();// 清除批处理中的数据
  32.                 }
  33.             }
  34.             /*
  35.             * 整数数组中的元素代表执行的结果代号
  36.             * SUCCESS_NO_INFO -2
  37.             * EXECUTE_FAILED  -3
  38.             * */
  39.             /*int[] ints = */
  40.             preparedStatement.executeBatch();
  41.             preparedStatement.clearBatch();
  42.         }catch (Exception e){
  43.             e.printStackTrace();
  44.         }finally {
  45.             if(null != preparedStatement){
  46.                 try {
  47.                     preparedStatement.close();
  48.                 } catch (SQLException e) {
  49.                     e.printStackTrace();
  50.                 }
  51.             }
  52.             if(null != connection){
  53.                 try {
  54.                     connection.close();
  55.                 } catch (SQLException e) {
  56.                     e.printStackTrace();
  57.                 }
  58.             }
  59.         }
  60.     }
  61. }

8_事务及回滚点

JDBC中使用事务 

事务回顾: 

事务概念:在逻辑上一组不可分割的操作,由多个sql语句组成,多个sql语句要么全都执行成功,要么都不执行.  原子性 一致性  隔离性 持久性

JDBC控制事物主要就是在学习如何让多个数据库操作成为一个整体,实现要么全都执行成功,要么全都不执行

在JDBC中,事务操作是自动提交。一条对数据库的DML(insert、update、delete)代表一项事务操作,操作成功后,系统将自动调用commit()提交,否则自动调用rollback()回滚,在JDBC中,事务操作方法都位于接口java.sql.Connection中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提交,倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常;此时就可以在异常捕获时调用rollback()进行回滚,回复至数据初始状态.事务开始的边界则不是那么明显了,它会开始于组成当前事务的所有statement中的第一个被执行的时候。事务结束的边界是commit或者rollback方法的调用

  使用事务保证转账安全性 

  1. package com.msb.test5;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.PreparedStatement;
  5. import java.sql.SQLException;
  6. /**
  7.  * @Author: Ma HaiYang
  8.  * @Description: MircoMessage:Mark_7001
  9.  */
  10. public class TestTransaction {
  11.     private static String driver ="com.mysql.cj.jdbc.Driver";
  12.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useServerPrepStmts=true&cachePrepStmts=true&&rewriteBatchedStatements=true";
  13.     private static String user="root";
  14.     private static String password="root";
  15.     public static void main(String[] args) {
  16.         testTransaction();
  17.     }
  18.     // 定义一个方法,向部门表增加1000条数据
  19.     public static void testTransaction(){
  20.         Connection connection = null;
  21.         PreparedStatement preparedStatement=null;
  22.         /*
  23.         * JDBC 默认是自动提交事务
  24.         * 每条DML都是默认提交事务的,多个preparedStatement.executeUpdate();都会提交一次事务
  25.         * 如果想手动控制事务,那么就不能让事务自动提交
  26.         * 通过Connection对象控制connection.setAutoCommit(false);
  27.         * 如果不设置 默认值为true,自动提交,设置为false之后就是手动提交了
  28.         * 无论是否发生回滚,事务最终会一定要提交的 提交我们建议放在finally之中进行提交
  29.         * 如果是转账的过程中出现异常了,那么我们就要执行回滚,回滚操作应该方法catch语句块中
  30.         *
  31.         * */
  32.         try{
  33.             Class.forName(driver);
  34.             connection = DriverManager.getConnection(url, user,password);
  35.             // 设置事务手动提交
  36.             connection.setAutoCommit(false);
  37.             String sql="update account set money =money- ? where aid = ?";
  38.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  39.             // 转出
  40.             preparedStatement.setDouble(1, 100);
  41.             preparedStatement.setInt(2, 1);
  42.             preparedStatement.executeUpdate();
  43.             // 产生异常
  44.             //int i =1/0;
  45.             // 转入
  46.             preparedStatement.setDouble(1, -100);
  47.             preparedStatement.setInt(2, 2);
  48.             preparedStatement.executeUpdate();
  49.         }catch (Exception e){
  50.             if(null != connection){
  51.                 try {
  52.                     connection.rollback();// 回滚事务
  53.                 } catch (SQLException ex) {
  54.                     ex.printStackTrace();
  55.                 }
  56.             }
  57.             e.printStackTrace();
  58.         }finally {
  59.             // 提交事务
  60.             if(null != connection){
  61.                 try {
  62.                     connection.commit();
  63.                 } catch (SQLException e) {
  64.                     e.printStackTrace();
  65.                 }
  66.             }
  67.             if(null != preparedStatement){
  68.                 try {
  69.                     preparedStatement.close();
  70.                 } catch (SQLException e) {
  71.                     e.printStackTrace();
  72.                 }
  73.             }
  74.             if(null != connection){
  75.                 try {
  76.                     connection.close();
  77.                 } catch (SQLException e) {
  78.                     e.printStackTrace();
  79.                 }
  80.             }
  81.         }
  82.     }
  83. }

 设置回滚点

  1. package com.msb.test5;
  2. import java.sql.*;
  3. import java.util.LinkedList;
  4. /**
  5.  * @Author: Ma HaiYang
  6.  * @Description: MircoMessage:Mark_7001
  7.  */
  8. public class TestTransaction2 {
  9.     private static String driver ="com.mysql.cj.jdbc.Driver";
  10.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useServerPrepStmts=true&cachePrepStmts=true&&rewriteBatchedStatements=true";
  11.     private static String user="root";
  12.     private static String password="root";
  13.     public static void main(String[] args) {
  14.         testAddBatch();
  15.     }
  16.     // 定义一个方法,向部门表增加1000条数据
  17.     public static void testAddBatch(){
  18.         Connection connection = null;
  19.         PreparedStatement preparedStatement=null;
  20.         LinkedList<Savepoint> savepoints =new LinkedList<Savepoint>();
  21.         try{
  22.             Class.forName(driver);
  23.             connection = DriverManager.getConnection(url, user,password);
  24.             connection.setAutoCommit(false);
  25.             String sql="insert into dept values (DEFAULT ,?,?)";
  26.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  27.             //设置参数
  28.             for (int i = 1; i <= 10663; i++) {
  29.                 preparedStatement.setString(1, "name");
  30.                 preparedStatement.setString(2, "loc");
  31.                 preparedStatement.addBatch();// 将修改放入一个批次中
  32.                 if(i%1000==0){
  33.                     preparedStatement.executeBatch();
  34.                     preparedStatement.clearBatch();// 清除批处理中的数据
  35.                     // 设置回滚点
  36.                     Savepoint savepoint = connection.setSavepoint();
  37.                     savepoints.addLast(savepoint);
  38.                 }
  39.                 // 数据在 100001条插入的时候出现异常
  40.                 if(i ==10001){
  41.                     int x =1/0;
  42.                 }
  43.             }
  44.             /*
  45.             * 整数数组中的元素代表执行的结果代号
  46.             * SUCCESS_NO_INFO -2
  47.             * EXECUTE_FAILED  -3
  48.             * */
  49.             /*int[] ints = */
  50.             preparedStatement.executeBatch();
  51.             preparedStatement.clearBatch();
  52.         }catch (Exception e){
  53.             if(null != connection){
  54.                 try {
  55.                     //Savepoint sp = savepoints.getLast();
  56.                     Savepoint sp = savepoints.get(4);
  57.                     if(null != sp){
  58.                         // 选择回滚点
  59.                         connection.rollback(sp);// 回滚
  60.                     }
  61.                 } catch (SQLException e2) {
  62.                     e2.printStackTrace();
  63.                 }
  64.             }
  65.             e.printStackTrace();
  66.         }finally {
  67.             if(null != connection){
  68.                 try {
  69.                     connection.commit();// 提交
  70.                 } catch (SQLException e) {
  71.                     e.printStackTrace();
  72.                 }
  73.             }
  74.             if(null != preparedStatement){
  75.                 try {
  76.                     preparedStatement.close();
  77.                 } catch (SQLException e) {
  78.                     e.printStackTrace();
  79.                 }
  80.             }
  81.             if(null != connection){
  82.                 try {
  83.                     connection.close();
  84.                 } catch (SQLException e) {
  85.                     e.printStackTrace();
  86.                 }
  87.             }
  88.         }
  89.     }
  90. }
9_JDBCAPI总结_阅读

JDBC API总结 

Connection接口 

•       作用:代表数据库连接

方法摘要 

 void 

close () 
   立即释放此   Connection  对象的数据库和 JDBC 资源,而不是等待它们被自动释放。

 void 

commit () 
            使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection  对象当前持有的所有数据库锁。

 Statement 

createStatement () 
            创建一个   Statement  对象来将 SQL 语句发送到数据库。

 CallableStatement 

prepareCall (String  sql) 
            创建一个   CallableStatement  对象来调用数据库存储过程。

 PreparedStatement 

prepareStatement (String  sql) 
            创建一个   PreparedStatement  对象来将参数化的 SQL 语句发送到数据库。

 PreparedStatement 

prepareStatement (String  sql, int autoGeneratedKeys) 
            创建一个默认   PreparedStatement  对象,该对象能获取自动生成的键。 

 void 

rollback () 
            取消在当前事务中进行的所有更改,并释放此   Connection  对象当前持有的所有数据库锁。

 void 

setAutoCommit (boolean autoCommit) 
            将此连接的自动提交模式设置为给定状态。 

  

DriverManager类 

作用:管理一组 JDBC 驱动程序的基本服务

应用程序不再需要使用 Class.forName() 显式地加载 JDBC 驱动程序。在调用 getConnection 方法时,DriverManager 会试着从初始化时加载的那些驱动程序以及使用与当前 applet 或应用程序相同的类加载器显式加载的那些驱动程序中查找合适的驱动程序。

方法摘要 

static Connection 

getConnection (String  url) 
            试图建立到给定数据库 URL 的连接。

static Connection 

getConnection (String  url, Properties  info) 
            试图建立到给定数据库 URL 的连接。

static Connection 

getConnection (String  url, String  user, String  password) 
            试图建立到给定数据库 URL 的连接。

  

Statement接口 

作用:用于将 SQL 语句发送到数据库中,或理解为执行sql语句

有三种 Statement对象:

Statement:用于执行不带参数的简单SQL语句;

PreparedStatement(从 Statement 继承):用于执行带或不带参数的预编译SQL语句;

CallableStatement(从PreparedStatement 继承):用于执行数据库存储过程的调用。

           

方法

作用

ResultSet   executeQuery(String   sql) 

执行SQL查询并获取到ResultSet对象

int   executeUpdate(String   sql) 

可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数

  PreparedStatement接口 

关系:public interface PreparedStatement extends Statement

区别

PreparedStatment安全性高,可以避免SQL注入 

PreparedStatment简单不繁琐,不用进行字符串拼接 

PreparedStatment性能高,用在执行多个相同数据库DML操作时 

ResultSet接口 

ResultSet对象是executeQuery()方法的返回值,它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。

ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。

ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行。

初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后指向最后一条记录的后面。

方法名 

说    明 

boolean   next()

将光标从当前位置向下移动一行

boolean   previous()

  游标从当前位置向上移动一行

void   close()

关闭ResultSet 对象

int   getInt(int colIndex)

以int形式获取结果集当前行指定列号值

int   getInt(String colLabel)

以int形式获取结果集当前行指定列名值

float   getFloat(int colIndex)

以float形式获取结果集当前行指定列号值

Float   getFloat(String colLabel)

以float形式获取结果集当前行指定列名值

String   getString(int colIndex)

以String 形式获取结果集当前行指定列号值

StringgetString(String   colLabel)

以String形式获取结果集当前行指定列名值

10_DAO模式

DAO(Data Access Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。

在核心J2EE模式中是这样介绍DAO模式的:为了建立一个健壮的J2EE应用,应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储.

简单来说,就是定义一个接口,规定一些增删改查的方法,然后交给实现类去实现, 它介于数据库和业务逻辑代码之间,这样当我们需要操作数据库是,根据接口定义的API去操作数据库就可以了,每个方法都是一个原子性的操作,例如:增加、修改、删除等

Dao模式要求项目必须具备这样几个结构

1实体类:和数据库表格一一对应的类,单独放入一个包中,包名往往是 pojo/entity/bean,要操作的每个表格都应该有对应的实体类

emp > class Emp  

dept > class Dept  

account > class Account 

2DAO 层:定义了对数据要执行那些操作的接口和实现类,包名往往是 dao/mapper,要操作的每个表格都应该有对应的接口和实现类

emp > interface EmpDao >EmpDaoImpl

dept > interface DeptDao> DeptDaoImpl

3Mybatis/Spring JDBCTemplate 中,对DAO层代码进行了封装,代码编写方式会有其他变化

项目的搭建 

1.创建项目

2.添加jar包

3.创建包

4.创建实体类Emp

5.创建后台的接口EmpDao和实现类EmpDaoImpl

导入各个层级的接口和页面之后的项目

项目结构截图如下

实体类代码

  1. public class Emp implements Serializable {
  2.     private Integer empno;
  3.     private String ename;
  4.     private String job;
  5.     private Integer mgr;
  6.     private Date hiredate;
  7.     private Double sal;
  8.     private Double comm;
  9.     private Integer deptno;
  1. public class Dept implements Serializable {
  2.     private Integer deptno;
  3.     private String dname;
  4.     private String loc;

DAO接口代码

  1. package com.msb.dao;
  2. import com.msb.pojo.Emp;
  3. /**
  4.  * @Author: Ma HaiYang
  5.  * @Description: MircoMessage:Mark_7001
  6.  */
  7. public interface EmpDao {
  8.     /**
  9.      * 向数据库Emp表中增加一条数据的方法
  10.      * @param emp 要增加的数据封装成的Emp类的对象
  11.      * @return 增加成功返回大于0 的整数,增加失败返回0
  12.      */
  13.     int addEmp(Emp emp);
  14.     /**
  15.      * 根据员工编号删除员工信息的方法
  16.      * @param empno 要删除的员工编号
  17.      * @return 删除成功返回大于0的整数,失败返回0
  18.      */
  19.     int deleteByEmpno(int empno);
  20. }

DAO实现类代码

  1. package com.msb.dao.impl;
  2. import com.msb.dao.EmpDao;
  3. import com.msb.pojo.Emp;
  4. import java.sql.*;
  5. /**
  6.  * @Author: Ma HaiYang
  7.  * @Description: MircoMessage:Mark_7001
  8.  */
  9. public class EmpDaoImpl implements EmpDao {
  10.     private static String driver ="com.mysql.cj.jdbc.Driver";
  11.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  12.     private static String user="root";
  13.     private static String password="root";
  14.     @Override
  15.     public int addEmp(Emp emp) {
  16.         // 向 Emp表中增加一条数据
  17.         Connection connection = null;
  18.         PreparedStatement preparedStatement=null;
  19.         int rows=0;
  20.         try{
  21.             Class.forName(driver);
  22.             connection = DriverManager.getConnection(url, user,password);
  23.             String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)";
  24.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  25.             //设置参数
  26.             preparedStatement.setObject(1,emp.getEname());
  27.             preparedStatement.setObject(2,emp.getJob() );
  28.             preparedStatement.setObject(3,emp.getMgr());
  29.             preparedStatement.setObject(4,emp.getHiredate());
  30.             preparedStatement.setObject(5,emp.getSal());
  31.             preparedStatement.setObject(6,emp.getComm());
  32.             preparedStatement.setObject(7,emp.getDeptno());
  33.             //执行CURD
  34.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  35.         }catch (Exception e){
  36.             e.printStackTrace();
  37.         }finally {
  38.             if(null != preparedStatement){
  39.                 try {
  40.                     preparedStatement.close();
  41.                 } catch (SQLException e) {
  42.                     e.printStackTrace();
  43.                 }
  44.             }
  45.             if(null != connection){
  46.                 try {
  47.                     connection.close();
  48.                 } catch (SQLException e) {
  49.                     e.printStackTrace();
  50.                 }
  51.             }
  52.         }
  53.         return rows;
  54.     }
  55.     @Override
  56.     public int deleteByEmpno(int empno) {
  57.         // 向 Emp表中增加一条数据
  58.         Connection connection = null;
  59.         PreparedStatement preparedStatement=null;
  60.         int rows=0;
  61.         try{
  62.             Class.forName(driver);
  63.             connection = DriverManager.getConnection(url, user,password);
  64.             String sql="delete from emp where empno =?";
  65.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  66.             //设置参数
  67.             preparedStatement.setObject(1,empno);
  68.             //执行CURD
  69.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  70.         }catch (Exception e){
  71.             e.printStackTrace();
  72.         }finally {
  73.             if(null != preparedStatement){
  74.                 try {
  75.                     preparedStatement.close();
  76.                 } catch (SQLException e) {
  77.                     e.printStackTrace();
  78.                 }
  79.             }
  80.             if(null != connection){
  81.                 try {
  82.                     connection.close();
  83.                 } catch (SQLException e) {
  84.                     e.printStackTrace();
  85.                 }
  86.             }
  87.         }
  88.         return rows;
  89.     }
  90. }

11_员工管理系统开发

DAO接口

  1. package com.msb.dao;
  2. import com.msb.pojo.Emp;
  3. import java.util.List;
  4. /**
  5.  * @Author: Ma HaiYang
  6.  * @Description: MircoMessage:Mark_7001
  7.  */
  8. public interface EmpDao {
  9.     /**
  10.      * 向数据库Emp表中增加一条数据的方法
  11.      * @param emp 要增加的数据封装成的Emp类的对象
  12.      * @return 增加成功返回大于0 的整数,增加失败返回0
  13.      */
  14.     int addEmp(Emp emp);
  15.     /**
  16.      * 根据员工编号删除员工信息的方法
  17.      * @param empno 要删除的员工编号
  18.      * @return 删除成功返回大于0的整数,失败返回0
  19.      */
  20.     int deleteByEmpno(int empno);
  21.     /**
  22.      * 查看数据库表格中所有的员工信息
  23.      * @return 所有员工信息封装的一个List<Emp>集合
  24.      */
  25.     List<Emp> findAll();
  26.     /**
  27.      * 根据员工编号修改员工其他所有字段的方法
  28.      * @param emp 员工编号和其他7个字段封装的一个Emp类对象
  29.      * @return 修改成功返回大于0的整数,失败返回0
  30.      */
  31.     int updateEmp(Emp emp);
  32. }
  1. package com.msb.dao;
  2. import com.msb.pojo.Dept;
  3. import java.util.List;
  4. /**
  5.  * @Author: Ma HaiYang
  6.  * @Description: MircoMessage:Mark_7001
  7.  */
  8. public interface DeptDao {
  9.     /**
  10.      * 查询全部门的方法
  11.      * @return Dept对象封装的List集合
  12.      */
  13.     List<Dept> findAll();
  14.     int addDept(Dept dept);
  15. }

DAO实现类

  1. package com.msb.dao.impl;
  2. import com.msb.dao.EmpDao;
  3. import com.msb.pojo.Emp;
  4. import java.sql.*;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /**
  8.  * @Author: Ma HaiYang
  9.  * @Description: MircoMessage:Mark_7001
  10.  */
  11. public class EmpDaoImpl implements EmpDao {
  12.     private static String driver ="com.mysql.cj.jdbc.Driver";
  13.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  14.     private static String user="root";
  15.     private static String password="root";
  16.     @Override
  17.     public int addEmp(Emp emp) {
  18.         // 向 Emp表中增加一条数据
  19.         Connection connection = null;
  20.         PreparedStatement preparedStatement=null;
  21.         int rows=0;
  22.         try{
  23.             Class.forName(driver);
  24.             connection = DriverManager.getConnection(url, user,password);
  25.             String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)";
  26.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  27.             //设置参数
  28.             preparedStatement.setObject(1,emp.getEname());
  29.             preparedStatement.setObject(2,emp.getJob() );
  30.             preparedStatement.setObject(3,emp.getMgr());
  31.             preparedStatement.setObject(4,emp.getHiredate());
  32.             preparedStatement.setObject(5,emp.getSal());
  33.             preparedStatement.setObject(6,emp.getComm());
  34.             preparedStatement.setObject(7,emp.getDeptno());
  35.             //执行CURD
  36.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  37.         }catch (Exception e){
  38.             e.printStackTrace();
  39.         }finally {
  40.             if(null != preparedStatement){
  41.                 try {
  42.                     preparedStatement.close();
  43.                 } catch (SQLException e) {
  44.                     e.printStackTrace();
  45.                 }
  46.             }
  47.             if(null != connection){
  48.                 try {
  49.                     connection.close();
  50.                 } catch (SQLException e) {
  51.                     e.printStackTrace();
  52.                 }
  53.             }
  54.         }
  55.         return rows;
  56.     }
  57.     @Override
  58.     public int deleteByEmpno(int empno) {
  59.         // 向 Emp表中增加一条数据
  60.         Connection connection = null;
  61.         PreparedStatement preparedStatement=null;
  62.         int rows=0;
  63.         try{
  64.             Class.forName(driver);
  65.             connection = DriverManager.getConnection(url, user,password);
  66.             String sql="delete from emp where empno =?";
  67.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  68.             //设置参数
  69.             preparedStatement.setObject(1,empno);
  70.             //执行CURD
  71.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  72.         }catch (Exception e){
  73.             e.printStackTrace();
  74.         }finally {
  75.             if(null != preparedStatement){
  76.                 try {
  77.                     preparedStatement.close();
  78.                 } catch (SQLException e) {
  79.                     e.printStackTrace();
  80.                 }
  81.             }
  82.             if(null != connection){
  83.                 try {
  84.                     connection.close();
  85.                 } catch (SQLException e) {
  86.                     e.printStackTrace();
  87.                 }
  88.             }
  89.         }
  90.         return rows;
  91.     }
  92.     @Override
  93.     public List<Emp> findAll() {
  94.         // 查询名字中包含字母A的员工信息
  95.         Connection connection = null;
  96.         PreparedStatement preparedStatement=null;
  97.         ResultSet resultSet=null;
  98.         List<Emp> list =null;
  99.         try{
  100.             Class.forName(driver);
  101.             connection = DriverManager.getConnection(url, user,password);
  102.             String sql="select * from emp";
  103.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  104.             //执行CURD
  105.             resultSet = preparedStatement.executeQuery();// 这里不需要再传入SQL语句
  106.             list=new ArrayList<Emp>() ;
  107.             while(resultSet.next()){
  108.                 int empno = resultSet.getInt("empno");
  109.                 String ename = resultSet.getString("ename");
  110.                 String job = resultSet.getString("job");
  111.                 int mgr = resultSet.getInt("mgr");
  112.                 Date hiredate = resultSet.getDate("hiredate");
  113.                 double sal= resultSet.getDouble("sal");
  114.                 double comm= resultSet.getDouble("comm");
  115.                 int deptno= resultSet.getInt("deptno");
  116.                 Emp emp =new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
  117.                 list.add(emp);
  118.             }
  119.         }catch (Exception e){
  120.             e.printStackTrace();
  121.         }finally {
  122.             if(null != resultSet){
  123.                 try {
  124.                     resultSet.close();
  125.                 } catch (SQLException e) {
  126.                     e.printStackTrace();
  127.                 }
  128.             }
  129.             if(null != preparedStatement){
  130.                 try {
  131.                     preparedStatement.close();
  132.                 } catch (SQLException e) {
  133.                     e.printStackTrace();
  134.                 }
  135.             }
  136.             if(null != connection){
  137.                 try {
  138.                     connection.close();
  139.                 } catch (SQLException e) {
  140.                     e.printStackTrace();
  141.                 }
  142.             }
  143.         }
  144.         return list;
  145.     }
  146.     @Override
  147.     public int updateEmp(Emp emp) {
  148.         // 向 Emp表中增加一条数据
  149.         Connection connection = null;
  150.         PreparedStatement preparedStatement=null;
  151.         int rows=0;
  152.         try{
  153.             Class.forName(driver);
  154.             connection = DriverManager.getConnection(url, user,password);
  155.             String sql="update emp set ename =? ,job=?, mgr =?,hiredate =?,sal=?,comm=?,deptno=? where empno =?";
  156.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  157.             //设置参数
  158.             preparedStatement.setObject(1,emp.getEname());
  159.             preparedStatement.setObject(2,emp.getJob() );
  160.             preparedStatement.setObject(3,emp.getMgr());
  161.             preparedStatement.setObject(4,emp.getHiredate());
  162.             preparedStatement.setObject(5,emp.getSal());
  163.             preparedStatement.setObject(6,emp.getComm());
  164.             preparedStatement.setObject(7,emp.getDeptno());
  165.             preparedStatement.setObject(8,emp.getEmpno());
  166.             //执行CURD
  167.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  168.         }catch (Exception e){
  169.             e.printStackTrace();
  170.         }finally {
  171.             if(null != preparedStatement){
  172.                 try {
  173.                     preparedStatement.close();
  174.                 } catch (SQLException e) {
  175.                     e.printStackTrace();
  176.                 }
  177.             }
  178.             if(null != connection){
  179.                 try {
  180.                     connection.close();
  181.                 } catch (SQLException e) {
  182.                     e.printStackTrace();
  183.                 }
  184.             }
  185.         }
  186.         return rows;
  187.     }
  188. }
  1. package com.msb.dao.impl;
  2. import com.msb.dao.DeptDao;
  3. import com.msb.pojo.Dept;
  4. import com.msb.pojo.Emp;
  5. import java.sql.*;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. /**
  9.  * @Author: Ma HaiYang
  10.  * @Description: MircoMessage:Mark_7001
  11.  */
  12. public class DeptDaoImpl implements DeptDao {
  13.     private static String driver ="com.mysql.cj.jdbc.Driver";
  14.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  15.     private static String user="root";
  16.     private static String password="root";
  17.     @Override
  18.     public List<Dept> findAll() {
  19.         // 查询名字中包含字母A的员工信息
  20.         Connection connection = null;
  21.         PreparedStatement preparedStatement=null;
  22.         ResultSet resultSet=null;
  23.         List<Dept> list =null;
  24.         try{
  25.             Class.forName(driver);
  26.             connection = DriverManager.getConnection(url, user,password);
  27.             String sql="select * from dept";
  28.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  29.             //执行CURD
  30.             resultSet = preparedStatement.executeQuery();// 这里不需要再传入SQL语句
  31.             list=new ArrayList<Dept>() ;
  32.             while(resultSet.next()){
  33.                 int deptno = resultSet.getInt("deptno");
  34.                 String dname = resultSet.getString("dname");
  35.                 String loc = resultSet.getString("loc");
  36.                 Dept dept =new Dept(deptno,dname,loc);
  37.                 list.add(dept);
  38.             }
  39.         }catch (Exception e){
  40.             e.printStackTrace();
  41.         }finally {
  42.             if(null != resultSet){
  43.                 try {
  44.                     resultSet.close();
  45.                 } catch (SQLException e) {
  46.                     e.printStackTrace();
  47.                 }
  48.             }
  49.             if(null != preparedStatement){
  50.                 try {
  51.                     preparedStatement.close();
  52.                 } catch (SQLException e) {
  53.                     e.printStackTrace();
  54.                 }
  55.             }
  56.             if(null != connection){
  57.                 try {
  58.                     connection.close();
  59.                 } catch (SQLException e) {
  60.                     e.printStackTrace();
  61.                 }
  62.             }
  63.         }
  64.         return list;
  65.     }
  66.     @Override
  67.     public int addDept(Dept dept) {
  68.         // 向 Emp表中增加一条数据
  69.         Connection connection = null;
  70.         PreparedStatement preparedStatement=null;
  71.         int rows=0;
  72.         try{
  73.             Class.forName(driver);
  74.             connection = DriverManager.getConnection(url, user,password);
  75.             String sql="insert into dept values(?,?,?)";
  76.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  77.             //设置参数
  78.             preparedStatement.setObject(1,dept.getDeptno());
  79.             preparedStatement.setObject(2,dept.getDname());
  80.             preparedStatement.setObject(3,dept.getLoc() );
  81.             //执行CURD
  82.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  83.         }catch (Exception e){
  84.             e.printStackTrace();
  85.         }finally {
  86.             if(null != preparedStatement){
  87.                 try {
  88.                     preparedStatement.close();
  89.                 } catch (SQLException e) {
  90.                     e.printStackTrace();
  91.                 }
  92.             }
  93.             if(null != connection){
  94.                 try {
  95.                     connection.close();
  96.                 } catch (SQLException e) {
  97.                     e.printStackTrace();
  98.                 }
  99.             }
  100.         }
  101.         return rows;
  102.     }
  103. }

EmpManageSystem类

  1. package com.msb.view;
  2. import com.msb.dao.DeptDao;
  3. import com.msb.dao.EmpDao;
  4. import com.msb.dao.impl.DeptDaoImpl;
  5. import com.msb.dao.impl.EmpDaoImpl;
  6. import com.msb.pojo.Dept;
  7. import com.msb.pojo.Emp;
  8. import java.text.ParseException;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.List;
  12. import java.util.Scanner;
  13. /**
  14.  * @Author: Ma HaiYang
  15.  * @Description: MircoMessage:Mark_7001
  16.  */
  17. public class EmpManageSystem {
  18.     private static Scanner sc =new Scanner(System.in);
  19.     private static EmpDao empDao =new EmpDaoImpl();
  20.     private static DeptDao deptDao=new DeptDaoImpl();
  21.     private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");;
  22.     public static void main(String[] args) {
  23.         while(true){
  24.             showMenu();
  25.             System.out.println("请录入选项");
  26.             int option  =sc.nextInt();
  27.             switch (option){
  28.                 case 1:
  29.                     case1();
  30.                     break;
  31.                 case 2:
  32.                     case2();
  33.                     break;
  34.                 case 3:
  35.                     case3();
  36.                     break;
  37.                 case 4:
  38.                     case4();
  39.                     break;
  40.                 case 5:
  41.                     case5();
  42.                     break;
  43.                 case 6:
  44.                     case6();
  45.                     break;
  46.                 case 7: 
  47.                                               sc.close();
  48.                                                 System.exit(0);
  49.                     break;
  50.                 default:
  51.                     System.out.println("请正确输入选项");
  52.             }
  53.         }
  54.     }
  55.     private static void case1(){
  56.         List<Emp> emps = empDao.findAll();
  57.         emps.forEach(System.out::println);
  58.     }
  59.     private static void case2(){
  60.         List<Dept> depts = deptDao.findAll();
  61.         depts.forEach(System.out::println);
  62.     }
  63.     private static void case3(){
  64.         System.out.println("请输入要删除的员工编号");
  65.         int empno=sc.nextInt();
  66.         empDao.deleteByEmpno(empno);
  67.     }
  68.     private static void case4(){
  69.         System.out.println("请输入员工编号");
  70.         int empno =sc.nextInt();
  71.         System.out.println("请输入员工姓名");
  72.         String ename =sc.next();
  73.         System.out.println("请输入员工职位");
  74.         String job =sc.next();
  75.         System.out.println("请输入员工上级");
  76.         int mgr =sc.nextInt();
  77.         System.out.println("请输入员工入职日期,格式为yyyy-MM-dd");
  78.         Date hiredate =null;
  79.         try {
  80.             hiredate = simpleDateFormat.parse(sc.next());
  81.         } catch (ParseException e) {
  82.             e.printStackTrace();
  83.         }
  84.         System.out.println("请输入员工工资");
  85.         double sal =sc.nextDouble();
  86.         System.out.println("请输入员工补助");
  87.         double comm=sc.nextDouble();
  88.         System.out.println("请输入员工部门号");
  89.         int deptno =sc.nextInt();
  90.         Emp emp=new Emp(empno, ename, job, mgr, hiredate, sal, comm,deptno);
  91.         empDao.updateEmp(emp);
  92.     }
  93.     private static void case5(){
  94.         System.out.println("请输入员工姓名");
  95.         String ename =sc.next();
  96.         System.out.println("请输入员工职位");
  97.         String job =sc.next();
  98.         System.out.println("请输入员工上级");
  99.         int mgr =sc.nextInt();
  100.         System.out.println("请输入员工入职日期,格式为yyyy-MM-dd");
  101.         Date hiredate =null;
  102.         try {
  103.             hiredate = simpleDateFormat.parse(sc.next());
  104.         } catch (ParseException e) {
  105.             e.printStackTrace();
  106.         }
  107.         System.out.println("请输入员工工资");
  108.         double sal =sc.nextDouble();
  109.         System.out.println("请输入员工补助");
  110.         double comm=sc.nextDouble();
  111.         System.out.println("请输入员工部门号");
  112.         int deptno =sc.nextInt();
  113.         Emp emp=new Emp(null, ename, job, mgr, hiredate, sal, comm,deptno);
  114.         empDao.addEmp(emp);
  115.     }
  116.     private static void case6(){
  117.         System.out.println("请录入部门号");
  118.         int deptno =sc.nextInt();
  119.         System.out.println("请录入部门名称");
  120.         String dname =sc.next();
  121.         System.out.println("请录入部门位置");
  122.         String loc =sc.next();
  123.         Dept dept =new Dept(deptno,dname,loc);
  124.         deptDao.addDept(dept);
  125.     }
  126.     public static void showMenu(){
  127.         System.out.println("************************************");
  128.         System.out.println("* 1 查看所有员工信息");
  129.         System.out.println("* 2 查看所有部门信息");
  130.         System.out.println("* 3 根据工号删除员工信息");
  131.         System.out.println("* 4 根据工号修改员工信息");
  132.         System.out.println("* 5 增加员工信息");
  133.         System.out.println("* 6 增加部门信息");
  134.         System.out.println("* 7 退出");
  135.         System.out.println("************************************");
  136.     }
  137. }

12_BaseDao抽取

BaseDAO代码

  1. package com.msb.dao;
  2. import com.msb.pojo.Emp;
  3. import java.lang.reflect.Field;
  4. import java.sql.*;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /**
  8.  * @Author: Ma HaiYang
  9.  * @Description: MircoMessage:Mark_7001
  10.  */
  11. public abstract class BaseDao {
  12.     private static String driver ="com.mysql.cj.jdbc.Driver";
  13.     private static String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
  14.     private static String user="root";
  15.     private static String password="root";
  16.     public int baseUpdate(String sql,Object ... args){
  17.         // 向 Emp表中增加一条数据
  18.         Connection connection = null;
  19.         PreparedStatement preparedStatement=null;
  20.         int rows=0;
  21.         try{
  22.             Class.forName(driver);
  23.             connection = DriverManager.getConnection(url, user,password);
  24.             preparedStatement = connection.prepareStatement(sql);
  25.             //设置参数
  26.             for (int i = 0; i <args.length ; i++) {
  27.                 preparedStatement.setObject(i+1, args[i]);
  28.             }
  29.             //执行CURD
  30.             rows =preparedStatement.executeUpdate();// 这里不需要再传入SQL语句
  31.         }catch (Exception e){
  32.             e.printStackTrace();
  33.         }finally {
  34.             if(null != preparedStatement){
  35.                 try {
  36.                     preparedStatement.close();
  37.                 } catch (SQLException e) {
  38.                     e.printStackTrace();
  39.                 }
  40.             }
  41.             if(null != connection){
  42.                 try {
  43.                     connection.close();
  44.                 } catch (SQLException e) {
  45.                     e.printStackTrace();
  46.                 }
  47.             }
  48.         }
  49.         return rows;
  50.     }
  51.     public List baseQuery(Class clazz,String sql,Object ... args) {
  52.         // 查询名字中包含字母A的员工信息
  53.         Connection connection = null;
  54.         PreparedStatement preparedStatement=null;
  55.         ResultSet resultSet=null;
  56.         List list =null;
  57.         try{
  58.             Class.forName(driver);
  59.             connection = DriverManager.getConnection(url, user,password);
  60.             preparedStatement = connection.prepareStatement(sql);//这里已经传入SQL语句
  61.             //设置参数
  62.             for (int i = 0; i <args.length ; i++) {
  63.                 preparedStatement.setObject(i+1, args[i]);
  64.             }
  65.             //执行CURD
  66.             resultSet = preparedStatement.executeQuery();// 这里不需要再传入SQL语句
  67.             list=new ArrayList() ;
  68.             // 根据字节码获取所有 的属性
  69.             Field[] fields = clazz.getDeclaredFields();
  70.             for (Field field : fields) {
  71.                 field.setAccessible(true);// 设置属性可以 访问
  72.             }
  73.             while(resultSet.next()){
  74.                 // 通过反射创建对象
  75.                 Object obj = clazz.newInstance();//默认在通过反射调用对象的空参构造方法
  76.                 for (Field field : fields) {// 临时用Field设置属性
  77.                     String fieldName = field.getName();// empno  ename job .... ...
  78.                     Object data = resultSet.getObject(fieldName);
  79.                     field.set(obj,data);
  80.                 }
  81.                 list.add(obj);
  82.             }
  83.         }catch (Exception e){
  84.             e.printStackTrace();
  85.         }finally {
  86.             if(null != resultSet){
  87.                 try {
  88.                     resultSet.close();
  89.                 } catch (SQLException e) {
  90.                     e.printStackTrace();
  91.                 }
  92.             }
  93.             if(null != preparedStatement){
  94.                 try {
  95.                     preparedStatement.close();
  96.                 } catch (SQLException e) {
  97.                     e.printStackTrace();
  98.                 }
  99.             }
  100.             if(null != connection){
  101.                 try {
  102.                     connection.close();
  103.                 } catch (SQLException e) {
  104.                     e.printStackTrace();
  105.                 }
  106.             }
  107.         }
  108.         return list;
  109.     }
  110. }

到实现类代码

  1. package com.msb.dao.impl;
  2. import com.msb.dao.BaseDao;
  3. import com.msb.dao.EmpDao;
  4. import com.msb.pojo.Emp;
  5. import java.sql.*;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. /**
  9.  * @Author: Ma HaiYang
  10.  * @Description: MircoMessage:Mark_7001
  11.  */
  12. public class EmpDaoImpl extends BaseDao implements EmpDao {
  13.     @Override
  14.     public int addEmp(Emp emp) {
  15.         String sql="insert into emp values(DEFAULT ,?,?,?,?,?,?,?)";
  16.         return baseUpdate(sql, emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno());
  17.     }
  18.     @Override
  19.     public int deleteByEmpno(int empno) {
  20.         String sql="delete from emp where empno =?";
  21.         return baseUpdate(sql, empno);
  22.     }
  23.     @Override
  24.     public List<Emp> findAll() {
  25.         String sql ="select * from emp";
  26.         return baseQuery(Emp.class, sql );
  27.     }
  28.     @Override
  29.     public int updateEmp(Emp emp) {
  30.         String sql="update emp set ename =? ,job=?, mgr =?,hiredate =?,sal=?,comm=?,deptno=? where empno =?";
  31.         return baseUpdate(sql, emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno());
  32.     }
  33. }

  1. package com.msb.dao.impl;
  2. import com.msb.dao.BaseDao;
  3. import com.msb.dao.DeptDao;
  4. import com.msb.pojo.Dept;
  5. import com.msb.pojo.Emp;
  6. import java.sql.*;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. /**
  10.  * @Author: Ma HaiYang
  11.  * @Description: MircoMessage:Mark_7001
  12.  */
  13. public class DeptDaoImpl extends BaseDao implements DeptDao {
  14.     @Override
  15.     public List<Dept> findAll() {
  16.         String sql="select * from dept";
  17.         return  baseQuery(Dept.class, sql);
  18.     }
  19.     @Override
  20.     public int addDept(Dept dept) {
  21.         String sql="insert into dept values(?,?,?)";
  22.         return baseUpdate(sql, dept.getDeptno(),dept.getDname(),dept.getLoc());
  23.     }
  24. }

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JDBC 连接数据库的过程一般包括以下步骤: 1. 加载数据库驱动程序:使用 Class 类的 forName() 方法加载 JDBC 驱动程序,例如: ``` Class.forName("com.mysql.jdbc.Driver"); ``` 2. 建立数据库连接:使用 DriverManager 类的 getConnection() 方法建立与数据库的连接,需要指定数据库的 URL、用户名和密码,例如: ``` String url = "jdbc:mysql://localhost:3306/mydatabase"; String username = "root"; String password = "mypassword"; Connection conn = DriverManager.getConnection(url, username, password); ``` 其中,"jdbc:mysql://" 表示连接的是 MySQL 数据库,"localhost:3306" 表示连接的是本地主机上的 MySQL 数据库,"mydatabase" 是数据库的名称,"root" 是数据库的用户名,"mypassword" 是数据库的密码。 3. 创建 Statement 对象:通过 Connection 对象的 createStatement() 方法创建 Statement 对象,用于执行 SQL 语句,例如: ``` Statement stmt = conn.createStatement(); ``` 4. 执行 SQL 语句:使用 Statement 对象的 execute() 方法执行 SQL 语句,例如: ``` String sql = "SELECT * FROM users"; ResultSet rs = stmt.execute(sql); ``` 5. 处理结果集:通过 ResultSet 对象处理查询结果,例如: ``` while (rs.next()) { String username = rs.getString("username"); String password = rs.getString("password"); // 处理查询结果 } ``` 6. 关闭数据库连接:使用 Connection 对象的 close() 方法关闭数据库连接,例如: ``` conn.close(); ``` 在实际应用中,还需要考虑异常处理、事务处理等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值