JAVA企业级开发-jdbc入门(09)

Posted 最苦逼的程序猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA企业级开发-jdbc入门(09)相关的知识,希望对你有一定的参考价值。

一、 jdbc介绍

JDBC全称为:Java DataBase Connectivity(java数据库连接)。

SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。

没有jdbc

有jdbc之后

二、 JDBC API 常用类与接口

jdbc的api在java.sql 以及 javax.sql的两个包下,以后同学们导包的时候要注意。

图中是几个核心类的关系。

DriverManager:数据库驱动管理类。

Connection:接口,建立数据库连接的一个接口。

Statement,preparedStatment,CallableStatment:接口:向数据库发送sql,并且得到数据库返回的信息。

ResultSet:结果集,Statement执行完sql---select之后,会返回结果,结果给了ResultSet

三、 JDBC 入门案例----重要

1、要连接mysql数据库。有一个mysql的数据库,并且要启动

2、创建一个数据库,创建一个表,把表添加一些数据。

3、找到msyql的驱动(jdbc的实现类),并且拷贝到工程中。build-path

4、书写java代码

5. 编程步骤

四、   jdbc-api详解

1. DriverManager 介绍

注意:这里只需要掌握 Class.forName(“com.mysql.jdbc.Driver”); 并且知道怎么来的

DriverManager驱动管理类。

 

static void

registerDriver(Driver driver)
          向 DriverManager 注册给定驱动程序。

参数:Driver---来自于你要连接的数据库(如果连接orcale,来自于oracle如果要连接mysql,来自于mysql)

registerDriver(new com.mysql.jdbc.Driver() );

不足:

1、对驱动api依赖性太高。

2、驱动会注册两次。(因为在mysql中的Driver中有静态代码块,已经注册了。)

com.mysql.jdbc.Driver 里面会静态代码块 加载两次

改进:

以后我们会使用Class.forname(“com.mysql.jdbc.Driver”); ---会把com.mysql.jdbc.Driver中的静态代码块执行一次。会实现驱动的注册。

jdbc提供的规范(要求驱动类中的静态代码块注册自己)。

java注册驱动的时候:

 

static Connection

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

 反射:把class文件加载,会执行类中的静态代码块

3. 建立与数据库的连接;

url:连接到某一个具体的数据库包括了 ip以及端口

user:数据库的用户名

password:数据库用户名对应的密码。

具体的调用方式:Connetion conn= DriverManager.getConnection()

 

3.a、 url介绍:指定一个具体的数据库

jdbc:mysql:///day07 ======jdbc:mysql://localhost:3306/day07?userUnicode=true&characterEncoding=utf8

jdbc:mysql:///sid ===== jdbc:mysql://localhost:3306/sid

要求是localhost,并且端口是3306才可以进行简写

前面是后面的简写。

jdbc:mysql://localhost:3306?key=value

url后面可以跟参数去解决数据库的乱码问题。

 

2、 Connection详解

需要注意的方法:

conn. prepareStatement (); 有待讲解

conn.createStatement();

2.a  Connection详解

与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。

如果想要发送sql到数据库,一定要通过这个连接。

Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法

Statement

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

 

与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。

如果想要发送sql到数据库,一定要通过这个连接。

Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:

 

 PreparedStatement

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

PreparedStatment预编译的sql。

prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象

---下午内容

PreparedStatment 继承 statement。

preparedStatement向数据库发送sql的。

 

 CallableStatement

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

 

prepareCall(sql):创建执行存储过程的callableStatement对象。仍然是statement对象的子接口。

--- 存储过程 ---oracle中

 

----明天内容

 void

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

开启事务

 

setAutoCommit(boolean autoCommit):设置事务是否自动提交。--开启事务

 void

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

 

commit() :在链接上提交事务。 ---与事务相关!!

 

 void

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

 

rollback() :在此链接上回滚事务。

 

3. Statement 详解

需要掌握的方法:

stmt.executeUpdate(sql);

stmt.executeQuery(sql);

Statement:向数据发送sql的对象,并且得到执行sql之后的结果。 接口

Jdbc程序中的Statement对象用于向数据库发送SQL语句, Statement对象常用方法:

 

ResultSet

executeQuery(String sql)  用于查询的sql
          执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。

 

resultSet = executeQuery(String sql) :用于向数据发送查询语句。select * from 表名

resultSet结果集。

 

 

 int

executeUpdate(String sql)
          执行给定 SQL 语句,该语句可能为 INSERTUPDATEDELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。

 

返回值说明:表示的是 sql语句执行之后,所改变的行数,影响的行数。

代码:

 

 

 boolean

execute(String sql)
          执行给定的 SQL 语句,该语句可能返回多个结果。

执行任意的sql语句。既可以执行insert,delete,update,还可以执行select。

返回值说明:

true:当执行select的时候返回true ---- 数据库返回来的内容是 resultSet

false:执行insert,update,,delete或者其他sql的时候返回false 数据库返回的内容是影响的行数。

 

 

如果执行的是 insert update delete 语句,程序希望获取影响的行数,可以通过getUpdateCount();获取影响的行数

 int

getUpdateCount()
          以更新计数的形式获取当前结果;如果结果为 ResultSet 对象或没有更多结果,则返回 -1。

 

如果执行的是select 语句:我们需要处理select语句执行之后获取的结果集

可以通过stmt.getResultSet(); 获取当前sql 执行之后得到的结果集

 

 ResultSet

getResultSet()
          以 ResultSet 对象的形式获取当前结果。

 

-----明天

addBatch(String sql) :把多条sql语句放到一个批处理中。

executeBatch():向数据库发送一批sql语句执行。

 

statement对象中的重要方法

executeUpdate(); ---update insert delete

executeQuery();---select

4、 ResultSet 详解

 

结果集:我们执行select 语句的时候,得到结果集

 

 

 boolean

absolute(int row)
          将光标移动到此 ResultSet 对象的给定行编号。

 

从1开始计数。

 void

afterLast()
          将光标移动到此 ResultSet 对象的末尾,正好位于最后一行之后。

 

 void

beforeFirst()
          将光标移动到此 ResultSet 对象的开头,正好位于第一行之前。

 

 

boolean

previous()
          将光标移动到此 ResultSet 对象的上一行。

 

光标向上滚动

 

 

5. 滚动结果集---了解

结果集是如何获取到的---statement对象。

statement 如何获取到的:conn.createStatment();

结果集:Statement.executeQuery();

设置结果集的类型,conn.createStatment(参数。);

参数的值:ResultSet

结果集类型

ResultSet.TYPE_FORWARD_ONLY       只能向前,只能调用next 不能向回滚动

ResultSet.TYPE_SCROLL_INSENSITIVE  支持结果集向回滚动,不能查看修改结果

ResultSet.TYPE_SCROLL_SENSITIVE    支持结果集向回滚动,查看修改结果

结果集并发策略

ResultSet.CONCUR_READ_ONLY 只读

ResultSet.CONCUR_UPDATABLE 支持修改

常见三种组合

ResultSet.TYPE_FORWARD_ONLY 和 ResultSet.CONCUR_READ_ONLY  (默认) 只读不支持向回滚动

ResultSet.TYPE_SCROLL_INSENSITIVE 和 ResultSet.CONCUR_READ_ONLY  只读,支持向回滚动

ResultSet.TYPE_SCROLL_SENSITIVE 和 ResultSet.CONCUR_UPDATABLE 支持向回滚动,支持对数据修改

rs提供了updateXXX( int , object);

               XXX表示的数据类型。

              第一个参数。表示列顺序,object具体的值

              updateXXX(String,object);

              第一个参数:列名

              第二个参数:要修改的值。

 void

updateRow()
          用此 ResultSet 对象的当前行的新内容更新底层数据库。

 

通过updateXX() 更改数据库中某一列的值。

不长使用:

1、遍历结果集的时候,我们通常值遍历一次。

2、我们查询的时候,只想获得数据,不希望去此时修改数据。

如果修改数据采用update 语句修改数据

 

6、 资源释放

连接资源是珍贵的,是有数目限制的。如果只有打开没有关闭,那么当达到一个限定之后,其他人将无法继续连接数据库。所以需要关闭连接。

 

五、   JDBC CRUD 操作

  1. insert

 

   2. update

全部代码:

 1 @Test
 2     public void update() throws ClassNotFoundException{
 3 //        1、加载驱动
 4         Class.forName("com.mysql.jdbc.Driver");
 5 //        2、建立链接
 6         String url = "jdbc:mysql://localhost:3306/day07";
 7         String user = "root";
 8         String password = "123456";
 9         Connection conn = null;
10         Statement stmt = null;
11         
12         try {
13             conn = DriverManager.getConnection(url, user, password);
14     //        3、获取statement对象
15             stmt = conn.createStatement();
16     //        4、执行sql
17             String sql = " update tb_user set age=20 where id = 1 ";
18             int resnum = stmt.executeUpdate(sql);
19             System.out.println("您成功修改了"+resnum+"条数据");
20     //        5、关闭链接
21         } catch (SQLException e) {
22             // TODO Auto-generated catch block
23             e.printStackTrace();
24         }finally{
25             try {
26                 if(stmt != null){
27                     stmt.close();
28                     stmt = null;
29                 }
30             } catch (SQLException e) {
31                 e.printStackTrace();
32             }
33             try {
34                 if(conn != null){
35                     conn.close();
36                     conn = null;
37                 }
38             } catch (SQLException e) {
39                 e.printStackTrace();
40             }
41         }
42     }
43 
44 

 

 

  3. delete

 

重点部分:

 

  4. select

 

 2 @Test
 3     public void select() throws ClassNotFoundException{
 4         
 5 //        加载驱动
 6         Class.forName("com.mysql.jdbc.Driver");
 7         String url = "jdbc:mysql://localhost:3306/day07";
 8         String user = "root";
 9         String password = "123456";
10         Connection conn = null;
11         Statement stmt = null;
12         ResultSet rs = null;
13         
14 //        定义一个list 存放所有用户信息
15         List<User> userList = new  ArrayList<User>();
16         
17         try {
18             conn = DriverManager.getConnection(url, user, password);
19 //            获取stmt对象
20             stmt = conn.createStatement();
21 //            定义一个sql
22             String sql = " select * from tb_user ";
23 //            执行sql
24             rs = stmt.executeQuery(sql);
25 //            对结果集进行遍历
26             while(rs.next()){
27                 int id = rs.getInt("id");
28                 String username = rs.getString("username");
29                 int age = rs.getInt("age");
30                 String sex = rs.getString("sex");
31                 //会把查询出来的内容进行封装, 封装成我们java中的对象
32                 User u = new User();
33                 u.setAge(age);
34                 u.setId(id);
35                 u.setSex(sex);
36                 u.setUsername(username);
37 //                把u放入到集合中
38                 userList.add(u);
39                 
40 //                System.out.println(id + username + age + sex);
41             }
42         } catch (SQLException e) {
43             // TODO Auto-generated catch block
44             e.printStackTrace();
45         }finally{
46             try {
47                 if(rs != null){
48                     rs.close();
49                     rs = null;
50                 }
51             } catch (SQLException e) {
52                 e.printStackTrace();
53             }finally{
54                 
55             }
56             ///
57             try {
58                 if(stmt != null){
59                     stmt.close();
60                     stmt = null;
61                 }
62             } catch (SQLException e) {
63                 e.printStackTrace();
64             }
65             try {
66                 if(conn != null){
67                     conn.close();
68                     conn = null;
69                 }
70             } catch (SQLException e) {
71                 e.printStackTrace();
72             }
73         }
74         
75         for(User u : userList){
76             System.out.println(u);
77         }
78     }

 

 

六、 JDBC 工具(JdbcUtil)类抽取

  1. 在src目录下创建jdbc.properties 文件

  2、 jdbc.properties文件里面的内容注意书写属性 的时候,不要书写 双引号和空格。

properties是配置文件L:里面已KEY=VALUE的形式保存

url=jdbc:mysql://localhost:3306/day07

user=root

password=123456

driverClass=com.mysql.jdbc.Driver

  3. jdbc工具类:

  a.  全局静态变量

  b.  静态块

静态块中完成的功能:

1、读取外部的配置文件(读取properties)

2、把properties的内容 赋值 到 当前变量 例如  url = prop.getProperty(“url”);

3、加载驱动

new fileImputStream(默认在根目录下)

 

   c、  获取连接方法:

 

  d、 释放资源方法:

 

七、   三层介绍

八、jdbc案例(登录)

----建表语句

create table user(

       id int primary key auto_increment,

       username varchar(30) unique not null,

       password varchar(30) not null

);

insert into user(id,username,password) values(null,\'zhangsan\',\'123456\');

创建一个User这个对象。 通常会把放到一个固定的包里面 entity bean domain

 

要属性一个业务。 登录。 一个查询数据库的过程。所以 在dao层提供一个查询数据库的方法。

没一层的方法写好之后,要进行单独的测试。

整体包的分类

包介绍

  2. dao的接口和实现

    a.  接口:

 

  b.  接口的实现:

 

   3. servcie层代码

     a. 接口:

    b.  实现:

  4.web层的实现

      username 和 pwd 是对应页面上input标签上name属性所对应text中填写的值 这就为什么如果你要写form标签必须要有name属性,方便传给web层

request 和 response 这个在后面会讲到

  5. 页面代码:

 

九、 sql注入问题

sql注入:在页面中输入sql的片段。达到串改程序中sql语句。

正常情况:

select * from user where username=\'zhangsan\' and password = \'123456\';

当sql被注入之后的语句:

select * from user where username=\'zhangsan\' and password = \'\' or \'1\'=\'1\'

造成系统的不安全不保密。

 

 十、 PreparedStatement解决sql注入

 

 

对sql进行预编译处理,sql的格式固定。可以防止预编译。

PrepareStatment 进行了预编译的处理,当下次执行相同格式的sql的时候,sql不会在进行编译。比statement的效率高。

statement每执行一次sql进行一次编译。

通过Connection

PreparedStatement

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

 

注意:sql提前创建好的。sql语句中需要参数。使用?进行站位。

举例:

select *from user where username=zhangsan and password = 123456;

使用?进行站位

 select * from user where username=? and password=?

 

1、conn.prepareStatement(sql); -----需要你事先传递sql。如果sql需要参数,使用?进行占位。

2、设置参数(执行sql之前):prepStmt.setXXX(int index, 要放入的值) -----根据不同类型的数据进行方法的选择。第一个参数表示的是?出现的位置。从1开始计数

有几个问号,就需要传递接个参数。

方法的参数说明:

第一个参数:int index ;表示的是问号出现的位置。 问号是从1开始计数

第二个参数:要问号的位置传入的值。

3、执行,不需要在传递sql了。

   prepStmt.executeQuery();---执行select

   prepStmt.executeUpdate();---执行insert,delete,update

 

为什么用preparestatement就可以防止SQL注入?

如果进行sql注入后 会把 ‘进行转义

 

 

  1. PreparedStatement优点

l  PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得,相对于Statement对象而言:

  • PreperedStatement可以避免SQL注入的问题。
  • Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
  • 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。方便阅读。

          使代码的可读性更高。

 以后在企业中几乎都是用PreparedStatement

 

十一、  JDBC批处理

 业务场景:当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。

 实现批处理有两种方式,第一种方式:

  • Statement.addBatch(sql)
  • 执行批处理SQL语句
  • executeBatch()方法:执行批处理命令
  • clearBatch()方法:清除批处理命令

  •  

 

  1. 批处理介绍和优点

  2. statement 批处理

Statement.addBatch(sql)

执行批处理SQL语句

executeBatch()方法:执行批处理命令

clearBatch()方法:清除批处理命令

采用Statement.addBatch(sql)方式实现批处理:

优点:可以向数据库发送多条不同的sql语句。

缺点: SQL语句没有预编译。当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。例如:

              Insert into user(name,password) values(‘aa’,’111’);

              Insert into user(name,password) values(‘bb’,’222’);

              Insert into user(name,password) values(‘cc’,’333’);

              Insert into user(name,password) values(‘dd’,’444’);

 

  3. preparestatement 批处理

 

  4.两种批处理比较

statement

就是可以发送不同格式的SQL

 

preparedStatement

 

 

以上是关于JAVA企业级开发-jdbc入门(09)的主要内容,如果未能解决你的问题,请参考以下文章

Spring入门

java入门:用jdbc实现宠物商店管理系统续篇

JDBC快速入门,如何使用JDBC操作数据库?

部分代码片段

Java新手入门200例124之用JDBC连接Mysql数据库

推荐net开发cad入门阅读代码片段