JDBC是java和数据库的连接,是一种规范,提供java程序与数据库的连接接口,使用户不用在意具体的数据库。
JDBC类型:类型1-JDBC-ODBC桥类型2-本地API驱动类型3-网络协议驱动类型4-本地协议驱动 类型四具有三层结构:1、JDBC API:提供java程序进行访问数据库的接口2、JDBC Driver Manager:管理JDBC Driver3、JDBC Driver :提供与不同·的数据库操作与连接JDBC 一般支持两层处理模型,
1、JDBC API:提供了应用程序对JDBC的管理连接;驱动程序管理器和数据库特定的驱动程序提供透明的连接到异构数据库。2、JDBC Driver API: 支持JDBC管理到驱动器连接。确保正确的驱动程序来访问每个数据源。该驱动程序管理器能够支持连接到多个异构数据库的多个并发的驱动程序。常用组件
DriverManager: 管理数据库驱动程序的列表。确定内容是否符合从Java应用程序使用的通信子协议正确的数据库驱动程序的连接请求。识别JDBC在一定子协议的第一个驱动器将被用来建立数据库连接。
Driver: 此接口处理与数据库服务器通信。很少直接直接使用驱动程序(Driver)对象,一般使用DriverManager中的对象,它用于管理此类型的对象。它也抽象与驱动程序对象工作相关的详细信息Connection : 此接口与接触数据库的所有方法。连接对象表示通信上下文,即,与数据库中的所有的通信是通过此唯一的连接对象。Statement : 可以使用这个接口创建的对象的SQL语句提交到数据库。一些派生的接口接受除执行存储过程的参数。CallableStatement :用来访问数据库中的存储过程。它提供了一些方法来指定语句所使用的输入/输出参数ResultSetMetaData:可用于获取关于ResultSet对象中列的类型和属性信息的对象ResultSet: 这些对象保存从数据库后,执行使用Statement对象的SQL查询中检索数据。它作为一个迭代器,可以通过移动它来检索下一个数据。SQLException: 这个类用于处理发生在数据库应用程序中的任何错误。以及PreperedStatement(从Statement扩展而来)相对Statement的优点:
1.没有SQL注入的问题。2.Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。3.数据库和驱动可以对PreperedStatement进行优化(只有在相关联的数据库连接没有关闭的情况下有效)。
JDBC连接步骤:
(1)注册驱动 (只做一次)(2)建立连接(Connection) (3)创建执行SQL的语句(Statement)(4)执行语句(5)处理执行结果(ResultSet)(6)释放资源1.1注册驱动
(1)Class.forName(“com.mysql.jdbc.Driver”);推荐这种方式,不会对具体的驱动类产生依赖。(2)DriverManager.registerDriver(com.mysql.jdbc.Driver);会造成DriverManager中产生两个一样的驱动,并会对具体的驱动类产生依赖。(3)System.setProperty(“jdbc.drivers”, “driver1:driver2”);虽然不会对具体的驱动类产生依赖;但注册不太方便,所以很少使用。1.2 建立连接Connection conn = DriverManager.getConnection(url, user, password);(1)url格式:JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…(2)User,password可以用“属性名=属性值”方式告诉数据库;1.3 创建执行SQL的语句
(1)Statement类的创建执行sql语句:String sql = “select * from table_name where col_name=‘李四’”;Statement st = conn.createStatement();ResultSet rs =st.executeQuery(sql)(2)PreparedStatement类的创建执行sql语句:
String sql = “select * from table_name where col_name=?”;PreparedStatement ps = conn.preparedStatement(sql);ps.setString(1, “col_value”); //将第一个?替换成col_valueResultSet rs = ps.executeQuery();1.4 处理执行结果(ResultSet)
//只有查询需要处理结果While(rs.next()){ rs.getString(“col_name”);rs.getInt(“col_name”);//…}1.5 释放资源
(1)释放ResultSet, Statement,Connection.(2)数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。 模板代码Connection conn = null;Statement st=null;ResultSet rs = null;try { //获得Connection//创建Statement//处理查询结果ResultSet} finally { //释放资源ResultSet, Statement,Connection}其中
(1)增、删、改用Statement.executeUpdate来完成,返回整数(匹配的记录数),这类操作相对简单。(2)查询用Statement.executeQuery来完成,返回的是ResultSet对象,ResultSet中包含了查询的结果;查询相对与增、删、改要复杂一些,因为有查询结果要处理。事务管理
完整的代码片段:
try{ con.setAutoCommit(false); //step① 把自动提交关闭Statement stm = con.createStatement();stm.executeUpdate("insert into person(id, name, age) values(520, 'X-Man', 18)");stm.executeUpdate("insert into Person(id, name, age) values(521, 'Super', 19)");//step② 正常的 DB 操作con.commit(); //step③ 成功主动提交} catch(SQLException e){ try{ con.rollback();} catch(Exception e){ e.printStackTrace(); } //step③ 失败则主动回滚}事务级别:
TRANSACTION_NONETRANSACTION_READ_UNCOMMITTED可读取未提交数据TRANSACTION_READ_COMMITTED避免脏读TRANSACTION_REPEATABLE_READ避免脏读、不可以重复读TRANSACTION_SERIALIZABLE避免脏读、不可以重复读和幻读,事务串行化,降低效率在Mysql中,只有当表的类型是INNODB的时候,才支持事务,所以需要把表的类型设置为INNODB,否则无法观察到事务.
修改表的类型为INNODB的SQL: alter table hero ENGINE = innodb; 查看表的类型的SQL show table status from how2java;JDBC批量处理
JDBC驱动程序不支持此功能。应该使用DatabaseMetaData.supportsBatchUpdates()方法来确定目标数据库支持批量更新处理。如果JDBC驱动程序支持此功能,则该方法返回true。addBatch()方法是PreparedStatement和CallableStatementis类中用于添加单个语句的批处理的声明。 executeBatch()将开始将所有语句组合到一起并执行。executeBatch()将返回一个整数数组,每个数组元素的表示为相应的更新语句的更新计数。添加语句进行批处理时,可以使用clearBatch()方法删除它们。此方法将删除addBatch()方法添加的所有语句。但是不能有选择性地选择某个语句来删除。 新类型Array 数组类型,主要用于保存一些类似于数组结构的数据。Sturct 结构Blob,大的二进制数据文件,最多存储 2G。Clob,大文本文件对象,最多存储 2G。面向对象
(ORM=Object Relationship Database Mapping)DAO=DataAccess Object 类定义―――>表定义类属性―――>表字段类关系―――>表关系对 象―――>表记录Oid(对象 id)―――>业务无关在数据库中每一条记录都对应一个唯一的 id;Id 通常是用来表示记录的唯一性的,通常会使用业务无关的数字类型字段的个数不会影响数据库的性能,表则越多性能越低。1、为每一个类建一张表。通过父类的 Oid 来体现继承关系。
特点:在子类表中引用父类表的主建作为自己的外建。优点:方便查询。属性没有冗余。支持多态。缺点:表多,读写效率低。生成报表比较麻烦。2、为每一个具体实现类建一个表特点:父类的属性被分配到每一个子类表中。优点:报表比较容易缺点:如果父类发生改变会引起所有子了表随之更改。并且不支持多态。数据有冗余。3、所有的类在一张表中体现,加一个类型辨别字段特点:效率高,查询不方便,用于重复字段不多时。优点:支持多态,生成报表很简单。缺点:如果任何一个类发生变化,必须改表。字段多,难以维护。(二)类关联关系对应表1,一对一关联,类关系对应成表时有两种做法:一是引用主键,也就是一方引用另一方的主键既作为外键有作为自身的主键。二是外键引用,一方引用另一方的主键作为自身的外键,并且自己拥有主键。2,一对多关联,也就是多端引用一端的主键当作外键,多端自身拥有主键。3,多对多关系,多对多关系是通过中间表来实现的,中间表引用两表的主键当作联合主键,就可以实现多对多关联 对时间的操作:ps.setDate(1, Data.valueOf(“2007-5-1”));ps.setTimestamp(2, new Timestamp(System.currentTimeMillis())); //对系统时间的截取获取自增长id
PreparedStatement ps =c.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);数据库连接池
编写连接池需实现java.sql.DataSource接口,DataSource接口中定义了两个重载的getConnection方法:Connection getConnection()Connection getConnection(String username, String password)实现DataSource接口,并实现连接池功能的步骤:1、在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中。2、实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取一个Connection返回给用户。3、当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。Collection保证将自己返回到LinkedList中是此处编程的难点。第三方库
1、数据库查询工具包DbUtils
https://commons.apache.org/proper/commons-dbutils/使用方法(1)核心类QueryRunner带有Connection的:
Int update(Connection conn, String sql, Object param);执行更新带一个占位符的sql
Int update(Connection conn, String sql, Object… param);执行更新带多个占位符的sqlInt[] batch(Connection conn, String sql, Object[][] params) 批处理T query(Connection conn ,String sql, ResultSetHandler<T> rsh, Object... params) 查询方法不带有Connection的:Int update( String sql, Object param); 执行更新带一个占位符的sql
Int update( String sql, Object… param);执行更新带多个占位符的sqlInt[] batch( String sql, Object[][] params); 批处理注意: 如果调用DbUtils组件的操作数据库方法,没有传入连接对象,那么在实例化QueryRunner对象的时候需要传入数据源对象:QueryRunner qr = new QueryRunner(DataSource ds);
(2)更新操作(包括delete 、insert、 update)
使用update函数和batch函数(3)查询DbUtils提供的封装结果的一些对象:BeanHandler: 查询返回单个对象
BeanListHandler: 查询返回list集合,集合元素是指定的对象ArrayHandler, 查询返回结果记录的第一行,封装对对象数组, 即返回:Object[]ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中ScalarHandler 查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)MapHandler 查询返回结果的第一条记录封装为mapMapListHandler 查询返回结果封装为List<map>如 final Student student = qr.query(conn, sql, new ResultSetHandler<Student>() {//自定义封装类
};再如 Student student = qr.query(conn,sql,new BeanHandler<Student>(Student.class),2);又如 List<Student> student = qr.query(conn,sql,new BeanListHandler<Student>(Student.class),3);更如 Map<String,Object> stuent = qr.query(conn,sql,new MapHandler());更又如 Long stuent = qr.query(conn,sql,new ScalarHandler<Long>());2、DBCP数据库连接池
(1)引入DBCP包(2)配置properties文件(http://commons.apache.org/proper/commons-dbcp/configuration.html)(3)加载配置文件,初始化连接池我们直接使用的最多的就是BasicDataSource类了,这个类主要是设置一些数据库连接池的参数,不过这些参数基本都是通过GenericObjectPool的实例来实现的。
在BasicDataSource中最重要的方法就是createDataSource方法了,这个方法中回创建一个GenericObjectPool实例来管理数据库连接(AbandonedObjectPool类已经不被推荐了,所以这里不考虑),最后这个方法返回的是PoolingDataSource的实例,这个类主要是对GenericObjectPool和数据库连接的一些代理实现。GenericObjectPool类主要是管理数据库连接池的,它主要实现了对数据库连接池参数的管理,例如连接池的最大数,它的创建连接时通过PoolableConnectionFactory的实例来实现的,不过它做了代理在创建连接的时候先检查了数据库的活动连接是不是已经达到了最大值,如果没有就继续创建,如果达到了参数设置的最大值就按指定的策略执行,默认的策略是当数据库连接池中的连接达到的最大值是在创建连接就会被阻塞(wait),这就是在上一篇中程序被挂起的主要原因。GenericObjectPool还可以检查最小的空闲连接,最大的空闲连接,驱逐超时的空闲连接。DriverConnectionFactory是实际获取数据库连接的类,它调用的是底层的数据库驱动。PoolableConnectionFactory主要实现了创建连接,关闭连接,验证连接,使连接钝化(关闭Statement,设置关闭标志,不是真的关闭),激活连接等操作。GenericObjectPool关于连接的操作基本就是通过它实现的。(https://my.oschina.net/u/2474629/blog/690748)
3、C3P0数据库连接池
使用(https://www.mchange.com/projects/c3p0/)
中文注解配置文件(https://blog.csdn.net/lscbfntxgt/article/details/68492500)主要类:ComboPooledDataSource: 和外界交互的类,主要负责 1. 设置连接池的配置 2. 获取连接C3P0PooledConnectionPoolManager:连接池大管家,负责连接池的生命周期,并且提供一系列生命周期需要的生态环境: 1. 定时检测任务AdminTaskTimer 2. 全局的线程池C3P0PoolConnectionPool:物理连接池对应的类,自身逻辑并不复杂,主要是通过委托给其代理的ResourcePool来实现“池”的逻辑BasicResourcePool:ResourcePool的实现类,抽象了一个“资源池”。刚才说到C3P0PooledConnectionPoolManager是管理连接池的生命周期的,那么BasicResourcePool就是管理池中连接的生命周期的。值得注意的是,BasicResourcePool并不是一个人在战斗,它还有一个小伙伴——BasicResourcePool.Manager来协助它一起管理池中的连接。 BasicResourcePool中包含几个任务: 1. 创建数据库连接任务:ScatteredAcquireTask,取代了老版本的AcquireTask 2. 销毁数据库连接任务:RemoveTask,这个任务应该不常用 3. 检测过期连接任务:CullTask,当检测到过期的连接时,则会去销毁这些连接 4. 验证空闲连接有效性任务:CheckIdleResourcesTask&&AsyncTestIdleResourceTask4、JDBC连接池、监控组件 Druid
(https://github.com/alibaba/druid)(https://blog.csdn.net/yanguo110/article/details/68944659)包括三部分:DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系。 DruidDataSource 高效可管理的数据库连接池。 SQLParser开启监控:
(https://blog.csdn.net/snakemoving/article/details/76285717)5、轻量级的关系型数据库中间件 Sharding-JDBC官网(https://gitee.com/Sharding-Sphere/sharding-sphere)文档(http://www.iocoder.cn/categories/Sharding-JDBC/)6、Spring框架组件 Spring JDBC
7、Spring Data (https://www.cnblogs.com/fzng/tag/SpringData/)Spring Data 包含多个子项目:Spring Data Commons - 每个Spring Data 项目的核心基础 (因此每一个Spring Data项目都使用统一的接口)
Spring Data Gemfire - 以Spring 的方式 提供GemFire 的简单配置和访问Spring Data JPA - 简化所有JPA标准数据库访问和操作(例如Hibernate MyBatis等等)Spring Data KeyValue - 简化所有以Map结构数据库及SPIs服务的构建Spring Data 模块 Spring Data LDAP - 提供 Spring LDAP.的基础支持Spring Data MongoDB - 为文档数据库 构建以Spring 基础的支持和数据访问组件Spring Data REST - 可以把Spring 数据仓库 输出为超媒体的形式的RESTFUL 资源Spring Data Redis - 提供简便的方式访问RedisSpring Data for Apache Cassandra - Apache Cassandra 的 Spring Data 模块Spring Data for Apache Solr - Apache Solr 的 Spring Data 模块Spring Data JPA 有什么
主要来看看Spring Data JPA提供的接口,也是Spring Data JPA的核心概念: 1:Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。 2:CrudRepository :是Repository的子接口,提供CRUD的功能 3:PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能 4:JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。 5:JpaSpecificationExecutor:用来做负责查询的接口 6:Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可Spring Data使用总结(https://segmentfault.com/a/1190000009211986)
数据库连接池:
https://wenku.baidu.com/view/6d4bb27602768e9951e73849.htmlhttps://wenku.baidu.com/view/a651a70b7cd184254b353549.html?sxts=1540359327532https://wenku.baidu.com/view/a7a856afd1f34693daef3e49.html?sxts=1540359257633http://commons.apache.org/proper/commons-dbcp/