第七周总结

本文详细介绍了SQL中的外键约束,包括如何添加和删除,以及级联操作。讨论了数据库的三大范式,多表查询的内连接和外连接。还涉及了SQL事务的特性,事务隔离级别以及MySQL视图的创建和使用。此外,讲解了JDBC在数据库操作中的应用,如使用PreparedStatement防止SQL注入,以及德鲁伊Druid数据库连接池的配置和优点。
摘要由CSDN通过智能技术生成

目录

SQL

外键约束

级联操作:

数据库三大范式:

多表查询:

内连接

外连接

sql事务:

事务的特点:

事务的隔离级别:

Mysql视图:

JDBC:

JDBC的使用:

德鲁伊druid:数据库连接池

连接池的好处:

如何使用:

commons-dbutils:

commons-dbutils的使用步骤:

注意事项:

事务:

单元测试: junit


SQL

外键约束

通过sql删除外键约束

alter table 表名 drop foreign key 外键名称;

通过sql增加外键约束

alter table 表名 add constraint 外键名称 foreign key(外键作用从表的字段名称) references 主表名(主键字段)

级联操作:

CASCADE(修改以及删除主表数据,从表数据随之改变)

创建表的时候添加外键的同时后面添加级联删除以及级联修改

CREATE TABLE 表名 (
  字段名称1 字段类型1,
  字段名称2 字段类型2,
  字段名称n,字段类型n
  
  字段名称,字段类型,  -- 外键要作用的字段名称
  声明 
  CONSTRAINT 
  外键名称     -- 外键名称:主表名_从表名_fk
  FOREIGN KEY (外键作用的从表的字段名称) 
  REFERENCES -- 关联
  主表名(主键字段)-- 主表的主键字段(就是id)
  on update cascade 
  on delete cascade 
) ;

通过sql添加外键的同时,设置级联操作(级联修改和级联删除)

alter table 表名 add
        constraint 外键名称
         foreign key  (外键作用从表的字段名称)
         references 主表名(主键字段)
         on update cascade
         on delete cascade ;

数据库三大范式:

1NF:保证数据库表中的每一列是不能再拆分的原子数据项

2NF:在1NF的基础上,数据库表中的每一个非主键字段必须完全依赖主键字段。

3NF:在2NF基础上,数据库表中的每一个非主键字段不能产生传递依赖,(必须在2NF上满足非主键字段必须完全依赖主键字段)

多表查询:

多表查询会出现笛卡尔乘积,A表中的每一列数据依次与B表进行组合,所以需要加入判断条件才可以正常使用

内连接

隐式内连接:

select 指定字段名称 form 表名1,表名2 where 判断条件

显式内连接

select 指定字段名称 from 表名l join 表名2 on 判断条件

外连接

左外链接

select 指定字段名称 from 表名1 left outer join 表名2 on 连接条件

右外连接

select 指定字段名称 from 表名1 right outer join 表名2 on 连接条件


数据的显示顺序决定于链接关键词那个表出现在前面,那个出现在前面那个就先显示

1、左外连接:是A和B的交集再并上A的所有数据。

2、右外连接:是A和B的交集再并上B的所有数据。

多表查询里面的子查询 (就是select嵌套select语句)

1.利用聚合函数查询出来的单列的数据和select语句进行嵌套
 

2.利用子查询 in(值1,值2,值3集合数据) 

3.将某张表select的结果集---当做一张虚表和其他表建立连接查询

sql事务:

事务将多个sql语句的执行看作一个整体,要么同时成功,要么同时失败,保证数据的一致性。

事务的特点:

原子性:每个事务都是同时成功,同时失败,不可再分。

一致性:执行事务前和执行事务后,数据从一种正确状态转为另一种正确状态

隔离性:事务与事务之间相互隔离,互不影响

持久性:事务一旦提交,做出的操作是永久性的。        

事务的隔离级别:

查询当前隔离级别:SELECT @@tx_isolation;  -- mysql8.0服务器版---SELECT 

设置隔离级别        
set global transaction  isolation level  (级别的名称) ;

读未提交:read uncommited

一个事务读取到另一个没有没有提交的事务(最不安全),出现"脏读" 

读已提交:read committed

有效防止脏读! 会出现另一种问题"不可重复读",

读取到自己本身没有提交的事务的数据前后两次不一致,本身这个事务没有提交,多次读取到的数据必须一致!

可重复读  :mysql的默认隔离级别 (repetable-read)

有效防止脏读,不可重复读,可能出现"幻读"

串行话:serializable

需要等待另一个事务提交才可以读取到数据

执行效率从大到小,安全性:从低到高。

Mysql视图:

是一个虚拟表:只是定义视图,表的数据来源于基础表中的(数据库中真实存在表)
作用:保证数据的安全性/简单性(快速查看到真实表的结构,类型....)

CREATE VIEW 视图名(一般是view_表名) AS 
SELECT 
字段名,

字段名,

字段名.....
FROM
  表名 ;

查看视图的内容

SELECT * FROM view_employee;

查询视表结构

DESC employee ;

查询当前库中的所有表以及视图的名称
 SHOW TABLES ;

查询当前库中的所有表以及视图的名称以及后面的table_type:表类型
 SHOW FULL TABLES ;

修改视图的内容
ALTER VIEW <视图名> AS <SELECT语句>

ALTER VIEW 视图名 
AS 
SELECT 
      id,NAME,salary  FROM employee ;

更新视图(视图添加数据/修改数据/删除数据,会直接影响基础表的内容,
一般很少去使用视图去更新基础表的内容)
 UPDATE  表名  SET 更改内容 WHERE 条件 ;
 

删除视图:就是drop  view 视图名称,多个视图名称;
只是的删除视图的定义,不会影响基础表的任何内容

重命名视图

renname  table 视图名 to 新视图名;

JDBC:

JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

JDBC的使用:

导入驱动包

注册驱动 class.forname(jdbc驱动包)

这里驱动包里面有一个静态代码块,加载的时候会自动注册驱动。

准备sql语句

String sql = "sql语句";

获取数据库的连接对象

使用下面的方法创建连接对象

public static Connection getConnection(String url, 统一资源定位符:连接的具体库
                        String user,  用户名
                        String password)登录mysql的密码
                        throws SQLException

 Connection conn = DriverManager.getConnection();

通过数据库的连接对象获取执行对象

java.sql.Connnection接口中包含Statement createStatement()方法,使用这个方法创建执行对象

Statement stmt = conn.createStatement();

执行对象执行sql

 int count = stmt.executeUpdate(sql); 增删改使用这个,返回参数是影响了几行的数字

ResultSet resultSet = stmt.executeQuery(sql);查询使用这个,返回的是一个结果集

resultSet.next()是用来判断是否有下一个结果,如果有则返回true,没有则是false。

 if(rs.next()){
                //列的索引值获取
                int id = rs.getInt(1) ;
                String name = rs.getString(2) ;
                int age = rs.getInt(3) ;
                String gender = rs.getString(4);
                String address = rs.getString(5);
                System.out.println(id+"\t"+name+"\t\t"+age+"\t"+gender+"\t"+address);
            }

这个是通过列的索引值来获取,从第一个开始。

getxx方法需要与数据库中的存储数据类型一致。

if(rs.next()){
                int id = rs.getInt("id") ; //id名称
                String name = rs.getString("name") ; //name名称
                int age = rs.getInt("age") ; //age名称
                String gender = rs.getString("gender") ; //gender
                String address = rs.getString("address") ; //address
                System.out.println(id+"\t"+name+"\t\t\t"+age+"\t"+gender+"\t"+address);
            }

这个是通过列的名称来获取

getxx方法同样需要与数据库中的存储数据类型一致。

但是Statement中sql是进行拼接的,效率低下而且会导致sql注入,会影响安全

所以可以使用它的子类PreparedStatement预编译对象。

一条sql:insert into/update/delete /select--->如果有参数那么参数全部都用? 占位符号代替

比如查询语句。

String sql = "select * from 表名 where id = ?"; 这里的?就代表一个占位符号

下一步创建PreparedStatement然后将sql语句传入

PreparedStatement statement = connection.prepareStatement(sql);

对sql语句进行赋值

statement.setInt(1,需要赋予的值)。

setxx需要与数据库的对应字段一致,1,则是代表给第几个问号赋值。

运行则是

statement.executeQuery(); 返回一个结果集,查询用这个

statment.executeUpdate();返回的是一个数字,增删改用这个

 Statement和 Statement的区别

1)共同点:
    都是可以发送sql到数据库的,都是执行对象,后者继承前者(java.sql.包下的接口)
2)不同点:
2.1)是否会造成sql注入
    Statement永远执行的是静态sql语句:语句中存在"硬编码",存在SQL的字符串拼接,就造成sql注入,不安全!
   Statement永远执行的是参数化的sql语句,全部参数都是"?",占位符号,有效防止sql的拼接,预防sql注入,提高执行sql的安全性!
2.2)是否会提高sql执行效率
    Statement:不会提高sql执行效率,
    获取执行对象,然后将sql语句发送数据库(没写一个sql,发一次!),频繁的操作访问数据库
    PreparedStatement:大大提高SQL执行效率
    参数化sql是在获取PreparedStatement,就已经发送给数据库了,然后在PreparedStatement赋值不同的值;

释放资源。

 stmt.close() ;
 conn.close();

德鲁伊druid:数据库连接池

#这些名称都是DruidDataSoure提供的参数
#连接数据库的驱动类
driverClassName=com.mysql.jdbc.Driver   
#连接数据库的url地址:统一资源定位符
url=jdbc:mysql://localhost:3306/myee2302_db_2
#用户名
username=root
#密码
password=123456
#连接池一旦创建,初始化5个连接数量
initialSize=5
#最大连接数量值:默认值8个,自己设定值,和maxIdel:最大空闲数量相等
maxActive=10
#最大等待时间:为毫秒值,一旦连接池中创建连接对象超过了最大连接数量,等待3秒中,如果还连接不上,连接池会产生错误日志,提示"连接超时"
maxWait=3000

java提供了java.sql.DataSource类,包含了Connection getConnection()抽象方法,连接池厂商继承了这个方法,德鲁伊就是继承了这个方法通过读取配置文件,自动封装对应属性,通过DruidDataSourceFactory的createDataSource(Properties prop)方法提供DataSource,然后
通过DataSource创建connection.

连接池的好处:

节省资源:当前连接池(DataSource接口)创建之后,就会初始化一些连接对象,节省连接对象的创建; 重复利用:当某个线程持有的连接对象被使用完之后,归还连接池等待下次利用; 提高性能:连接池中:只需要配置好这些连接参数(最基本参数:数据库的相关信息)/连接池中的优化参数,DataSource里的实 现类---DruidDataSource自己封装这里面的所有连接参数;(还可以不断监控连接池中连接数量的变化)

如何使用:

1)导包druid-1.1.10.jar /mysql的驱动jar包

2)准备配置文件 url=jdbc:mysql://localhost:3306库名 driverClassName=com.mysql.jdbc.Driver username=root password=123456 initialSize=初始化连接数量 maxActive=最大激活数量 minIdel=最小空闲数量 maxidel=最大空闲数量 maxWait=最大等待时间毫秒值

3)创建数据源javax.sql.DataSoure接口对象,

//属性集合列表 Properties prop = new Properties() ; //读取src下面的druid.propertites---->当前类的字节码文件对象获取类加载器--->资源文件的输入流对象 prop.load(字节输入流) ;

DataSource ds = DruidDataSourceFatory.createDataSource(prop) ;

Connection conn = ds.getConnection() ;

commons-dbutils:

commons-dbutils的使用步骤:


1)导包 commons-dbutils-1.6.jar
2)创建执行器 QueryRunner---> 底层PreparedStatement
public QueryRunner(DataSource ds) 参数就是数据源--->自定义工具获取到了数据源 (自动提交)
public QueryRunner():创建执行器,手动提交


3)准备好sql语句

DML语句---添加/修改/删除
                  insert into
                  update
                  delete from...

QueryRunner提供通用的更新操作:
public int update(Connection conn, String sql, Object... params) throws SQLException  :手动提交
public int update(String sql, Object... params):自动提交

DQL语句--- 查询语句

QueryRunner提供的通用查询操作
public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException
第一个参数:查询的sql语句
第二个参数:ResultSetHandler结果集的处理
它的子实现类:BeanHandler---->将查询的某一条记录封装到实体了中(JavaBean:是具体类,属性私有,对外提供setXXX()/getXXX)
public BeanHandler(Class<T> type) --->  参数针对查询的记录--封装到类名.class中

子实现类:BeanListHandler<T>    ---将查询的多条记录封装到List集合中,List集合都是当前类对象

public BeanListHandler(Class<T> type)
子实现类:

ScalarHandler:通过聚合函数(count(列名称),其他max(xx),avg(xxx))查询单行单的列的数据
的结果封装到Object类中
 第三个参数:就是赋值的实际参数params,没有参数可以不写

注意事项:


使用commons-dbutils工具库:无论添加/删除/修改/查询数据,
必须保证实体类的属性名称和表的字段名称一一对应,否则数据封装不上去的,永远是null!
如果不对应,可以在(查询语句)--->给这字段给别名(保证别名和实体类的属性名称一致)

实体类的属性名称不要出现大写字母,否则也可能是null值!

事务:

在修改数据库时,可能会因为中间代码出现问题导致程序出错,那么前面修改了,后面没修改成功,为了防止这种事情发生,所以加入了事务,在操作开始前设置开启事务,改为手动提交,如果执行完毕,那么在代码结尾除加入提交事务,那么修改完毕,如果失败的话,则会抛出异常,那么在异常后面加入事务回滚,那么就会回滚事务,取消掉之前的修改。

开启事务:

void setAutoCommit(boolean autoCommit) throws SQLException

connection.setAutoCommit(false); false改为手动提交

提交:

void commit() throws SQLException

回滚:

void rollback() throws SQLException

单元测试: junit

导包 junit以及依赖包
编写测试类---编写测试方法---上面加入一个注解@Test(标记它是单元测试方法,单独运行)
正常使用单元测试:
junit包--提供了Assert:断言 我们的结果是否和预期结果相同--提供一些方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值