1.  数据库(JDBC、DBMS)

 1. JDBC:JNDI--DataSource---连接池(c3p0\dbcp\Proxool)----DriverManager---connection

oracle的数据库驱动:oracle.jdbc.driver.OracleDrive

mysql 的数据库驱动:com.mysql.jdbc.Driver

 

驱动的加载方法有:

     a、调用方法class.forName

     b、通过添加系统的jdbc.drive属性

     c、通过registerDriver方法注册

----------------有待整理-----------------

 

JDBC-ODBC方式实现:

建立JDBC-ODBC桥接器,(使用java.lang中的class类,使用静态方法forName加载驱动)

创建ODBC数据源,

建立与ODBC的连接(可能异常)

----------------有待整理-----------------

 

 

 

2. 数据库连接方式有两种:

  1.建立JDBC--ODBC桥接器(微软提供)依赖平台,

  2.直连纯Java数据库驱动(数据库厂家提供例如 mysql的mysql-connector-java.jar)

 

3.数据库实现查询功能流程:

    1. 加载JDBC驱动

    2.建立并获取数据库连接----->通过连接池建立多个连接备用,使用什么连接池用户自定

    3. 创建JDBC statements对象--

    4.设置SQL语句的传入参数->用if,else判断传入的参数#变量名#占位符 $变量名$非占位符

    5.执行SQL语句并获得查询结果

    6.对结果进行转换处理并返回

    7.释放相关资源

 

经过优化之后:

(1) 使用数据库连接池对连接进行管理

(2) SQL语句统一存放到配置文件中

(3) SQL语句变量和传入参数的映射以及动态SQL

(4) 动态SQL语句处理

(5) 对数据库操作结果的映射和结果缓存

(6) SQL语句的重复

 

4. PreparedStatement和Statement的区别:

1.创建时:

    1) Statement statement = conn.creatStatement();

    2) PrepareStatement preStatement = conn.PrepareStatement(sql);

2.执行时:

    1) ResultSet  rSet = statement.executeQuery(sql);

    2) ResultSet  pSet=preStatement.executeQuery();

PreStatement 有预编译过程,已经绑定sql,之后无论执行什么遍,都不会再去编译。

而statement不同,如果执行多遍,就需要编译多遍,所以prestatement效率比较高。

3)安全性:prepareStatement是预编译的,所以可以有效的防止SQL注入等问题。

4)可读和维护:后期维护prepareStatement也比较好读。

 

5. DBMS:数据库管理系统,事务具有持久性、一致性、原子性、隔离性。

持久性实现恢复管理子系统,一致性实现并发控制子系统,

原子性实现完整子系统,隔离性实现安全控制管理子系统。

一般关系数据模型和对象数据模型之间有以下对应关系:表对应类、记录对应对象、字段对应属性,ORMapping只是规定了结构和集的映射。

 

6. 数据库的优化:

1.索引:

项目中使用到的内容:

1. 外键约束:

CREATE TABLE review (
  id int(11) NOT NULL AUTO_INCREMENT,
  content varchar(4000) DEFAULT NULL,
  uid int(11) DEFAULT NULL,
  pid int(11) DEFAULT NULL,
  createDate datetime DEFAULT NULL,
  PRIMARY KEY (id),
  CONSTRAINT fk_review_product FOREIGN KEY (pid) REFERENCES product (id),
    CONSTRAINT fk_review_user FOREIGN KEY (uid) REFERENCES user (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

 

外键约束使用最多的两种情况:

  1)父表更新时子表也更新,父表删除时如果子表有匹配的项,删除失败;

  2)父表更新时子表也更新,父表删除时子表匹配的项也删除。

  前一种情况,在外键定义中,我们使用ON UPDATE CASCADE ON DELETE RESTRICT;
  后一种情况,可以使用ON UPDATE CASCADE ON DELETE CASCADE。
使用案例:
(1)创建表:
 代码如下    

CREATE TABLE IF NOT EXISTS `article` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category_id` int(11) NOT NULL,
`name` char(16) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_1` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
 
 
INSERT INTO `article` (`id`, `category_id`, `name`) VALUES
(1, 1, '文章1');
 
 
CREATE TABLE IF NOT EXISTS `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(16) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
 
 
 
INSERT INTO `category` (`id`, `name`) VALUES
(1, '分类1');


创建外键约束:
 代码如下  

ALTER TABLE `article`
ADD CONSTRAINT `fk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`);


(2)删除主表category中数据:delete FROM `category` WHERE id=1,会报错:
 #1451 - Cannot delete or update a parent row: a foreign key constraint fails (`test`.`article`, CONSTRAINT `fk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`))
(3)从表article中,添加不存在的category_id:insert into article(category_id,name) values(2,'分类2') 会报错:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`test`.`article`, CONSTRAINT `fk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`))

(4)更改更新删除约束
 代码如下   

--删除外键
ALTER TABLE article DROP FOREIGN KEY fk_1
--添加外键
ALTER TABLE `article` ADD CONSTRAINT `fk_1` FOREIGN KEY ( `category_id` )
REFERENCES `category` ( `id` )
ON DELETE CASCADE ON UPDATE CASCADE


此时如下操作:
 代码如下     复制代码

--此时article中的记录也会被删除
delete from category where id=1;
--此时article中的category_id也会被更新成3
UPDATE `test`.`category` SET `id` = '3' WHERE `category`.`id` =2;

 

 

 

 

 

2020-04-10:

Hibernate 使用 MySQL:

Hibernate 在执行 insert into 时,发现:

Caused by: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (5,357 > 1,024). You can change this value on the server by setting the 'max_allowed_packet' variable.

 

这个问题 在 使用 jdbc 执行插入操作时没有出现过,怀疑是 hibernate 在执行 事务操作时,打包的数据量超过了 1024kb 造成的。

 

修改mysql 服务参数,并重启

查询 当前的 值:  show VARIABLES like '%max_allowed_packet%';

设置 该值为  20M  set global max_allowed_packet = 2*1024*1024*10;

2. 事务操作 MySQL 插入数据, id 自增问题

当 在一个事务中,执行了一次 插入操作,但是没有提交,然后关闭了连接, 在执行一次插入操作,就发现 自增的id 不是连续醒的。

mysql驱动类型 mysql驱动类名称_bc

因为在 MySQL 启动的时候,执行了 select max(*) from table ,获取了当前的最大id(注意,此处是id号,并不是行号), 并将该值保存在内存中,当第一次插入操作执行 auto_increment 时,auto_increment的计数器的值 + 1 ,但是没有提交就关闭了数据库连接,所以数据库没有该条数据。

再执行一次事务插入操作,并提交。使用 auto_increment的计数器的值 + 1 作为该记录的 id 值插入数据库。

 

为此,特意,在一次事务失败之后,重启数据库测试:

想象:执行一次事务 插入操作,不提交,此时 auto_increment 的 值 应该+1

          重启 数据库,此时 auto_increment 获取数据库 表的 最大id值,

          再执行一次完整的事务插入操作,并提交,此时 数据库的 id 应该是连续的。

关于 id自增 是不是 临时存入数据库 还是 保存到 日志文件中,有时间了看看MySQL的书籍。