持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库来完成。
持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中
在Java中,数据库存取技术可分为如下几类:
JDBC是java访问数据库的基石,JDO, Hibernate等只是更好的封装了JDBC
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,使用这个类库可以以一种标准的方法、方便地访问数据库资源
JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题
JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程
JDBC接口(API)包括两个层次:
JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果
管理一组 JDBC 驱动程序的基本服务
在建立连接的时候需要四个参数连接数据库
用户名、密码、url、driver
对于 MySql数据库连接: jdbc:mysql://localhost:3306/test
对于 SQLServer 数据库连接:jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
对于 MYSQL 数据库连接:jdbc:mysql://localhost:3306/sid
如果是远程连接数据库,则将相应的localhost换成相应的ip地址
用于执行静态 SQL 语句并返回它所生成结果的对象
通过Statement 对象的 excuteQuery() 查询到的结果集是ResultSet就是一张数据表
java.sql.DriverManager:用来装载驱动程序,获取数据库连接。
java.sql.Connection:完成对某一指定数据库的联接
java.sql.Statement:在一个给定的连接中作为SQL执行声明的容器,他包含了两个重要的子类型。
Java.sql.PreparedSatement :用于执行预编译的sql声明
Java.sql.CallableStatement:用于执行数据库中存储过程的调用
java.sql.ResultSet:对于给定声明取得结果的途径
用户名、密码分别为登录oracle数据库的用户名、密码
驱动查找:ojdbc6.jar包下的“oracle.jdbc.driver”包下的“OracleDriver.class”
驱动driver=”oracle.jdbc.driver.OracleDriver ”;
连接url=”jdbc:oracle:thin:@localhost:1521:orcl ”;
“DriverManager.getConnection(url, username, password)”
public
测试结果:如果测试成功,会相应返回一个内存地址,如果连接失败则会提示相应的连接错误提示
在src文件夹下存放属性配置文件“jdbc.properties”,里面相应包含数据库连接所需要的四个属性
public
测试结果:如果测试成功,会相应返回一个内存地址,如果连接失败则会提示相应的连接错误提示
/**
考虑到之后的测试中始终需要对相应的文件、连接进行操作,为了保证操作的安全性,每次操作结束之后均要关闭相应的连接,因此为了避免重复代码的冗余,考虑将关闭连接的操作封装为一个方法freeAll(Connection conn,Statement st,ResultSet rs)
//关闭连接
在之后的练习中仍有许多内容需要进一步加以完善,改进,从而进一步优化代码,需要自己加以把握,巩固!不断地优化自己的代码设计思想
public
结果分析:可结合数据库进行测试,查看结果的正确性
1.创建表stu
2.新增数据(多次修改sql语句、执行)
3.删除数据
4.修改数据
5.查询所有的数据
缺点:代码虽然简单、形式单一,但却没有很好的通用性(将sql语句写死!),不能很好地实现需求,可以作为简单参考,在此基础上应该更好地完善,下述通过绑定变量方式更新进行叙述
public
结果分析:可结合数据库进行测试,查看结果的正确性
1.创建表stu
2.新增数据
3.删除数据
4.修改数据
5.查询单一数据
6.查询所有数据
创建表格,插入指定的数据,设计输入显示实现数据的录入、删除、修改、信息的查询
结合题目需求,在前面所学案例的基础上可以进一步对代码继续进行优化
1.设计相应的界面提示,将获取用户输入部分独立出来
2.根据用户的输入决定要执行的sql语句,再将String类型的sql传入相应的方法中
3.考虑重复代码的问题,尝试着将部分重复代码进行整合,整合为一个通用的方法。此处可以考虑将insert、delete、update方法整合成为一个通用的方法,通过传入的参数决定要执行的操作(根据不同的需求传入sql语句,以及所需的参数)
可以直接根据内容拼接sql语句,也可通过预编译sql语句,将相关参数传入后执行
4.另外独立封装增删改查方法进行测试
public
PersonCRUD .java
public
Menu .java
public
PersonCRUD2 .java
public
Menu2 .java
public
在数据库中创建相应的表格进行测试
public
一次性插入太多数据可能会报相应的错误,因此在创建连接的时候要注意连接的使用量、最大连接数
ORA-12519, TNS:no appropriate service handler found
public
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。事务的完成由若干个DML语句组成的。
在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态
为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态
事务的操作:先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,如果回退(ROLLBACK),数据库管理系统将放弃所作的所有修改而回到开始事务时的状态
数据库事务有四大特性: ACID --> 原子性 一致性 隔离性 持久性
指事务在逻辑上是不可分割的操作单元,所有的语句要么都执行成功,要么都执行失败并进行撤销。
从一个状态转换为另外一个状态
事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束
隔离性是针对并发而言。所谓的并发是指数据库服务器同时执行多个事务,如果在执行的过程中不采取有效的专门控制机制,并发事务之间会发生相互干扰
隔离性就是隔离并发运行的多个事务避免产生相互影响
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
事务一旦提交对数据的修改就是持久性的,数据已经从内存转移到了外部服务器上,并执行了固化的步骤
由于数据库的隔离性导致的并发问题包括以下内容
对于同时运行的多个事务,当这些事务访问数据库中相同的数据,如果没有采取必要的隔离机制将会导致各种并发问题。
对于两个事务T1,T2 。 T1读取了已经被T2更新但是还没有提交的字段之后,如果T2发生了回滚,T1读取的内容就是无效的。
对于两个事务T1,T2。T1读了一个字段,然后T2更新了该字段之后,T1再次读取同一个字段,两次读取的值就是不同的。
对于两个事务T1,T2 T1从一个表中读取一个字段,然后T2在该表中插入一个新的行之后,如果T1再次读取这个表发现数据行数变多。
是第一次提取的内容被第二次提交的内容进行了覆盖
数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.
一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱
为了解决并发问题 数据库定义了四种隔离级别。隔离级别越高效率越慢,根据业务选择一个合适的隔离级别,在性能和安全上做平衡。
允许事务读取未被其他事务提交的变更,脏读,不可重复读,(虚读)幻读问题都会出现
只允许事务读取已经被其他事务提交的变更,可以避免脏读,但是不可重复读和幻读依然存在
确保事务可以多次从一个字段中读取相同的值,这个事务存在期间,禁止其他事务对这个字段进行更新,可以避免脏读,不可重复读但是幻读依然存在。
确保可以从一个表中读取相同的行,这个事务存在期间禁止其他事务对该表进行插入、更新和删除操作。所有的并发问题都可以避免,但是性能十分低下。
并不是所有的数据库都支持这四种隔离级别
1 read uncommited
2 read commited
4 repeatable read
8 serializable
利用事务实现转账小程序,在数据库中创建了如下的表
--
如果转账过程中没有出现异常,则正常操作,余额有所变动,但如果转账过程中出现差错,则事务发生回滚,余额不会发生变动
public
在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤:
这种模式开发,存在的问题:
普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用,若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。
这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。
数据库连接池:
优势:
搜索才c3p0相关信息,可以从c3p0官网上下载,也可以从maven网站进行搜索下载
https://www.mchange.com/projects/c3p0/
http://mvnrepository.com/
此外还要下载相应的依赖包
下载完成后加对应jar包加载到指定项目中,随后查看c3p0官网中相关的配置信息
https://www.mchange.com/projects/c3p0/apidocs/index.html
在当前工程下创建配置文件“c3p0-config.xml”,如果没有指定的路径,默认是在src目录下查找,因此要将相应的配置文件放置在src目录下
测试连接
public
连接成功结果:
c3p0在底层做了许多优化工作,目前暂时不需要做过多深究,简单了解并应用即可
http://mvnrepository.com/artifact/commons-dbutils/commons-dbutils
加载dbutils jar包到指定的工程
--创建worker表简单实现dbutils的测试
与此相对应的是要创建相应的Model,其属性与数据库中的表的列一一对应,测试则是通过Junit进行单元测试
public
/**
public