回顾了一下, 在今年一月份开始看Java的时候, 快速总结了一遍JDBC的知识, 做了一个脑图, 至今回头看看效果还不错, 可以迅速上手.
这次再查缺补漏一下吧.
JDBC的结构
Oracle在JDBC方面, 主要规定了两大标准, 一个是JDBC API, 一个是JDBC 驱动器 API,也就是Driver接口.
Java应用程序打交道的是JDBC API ,JDBC API去寻找DriverManager类进行工作, DriverManager类根据在其中注册的Driver实现与数据库的具体沟通.
所以要使用什么样的数据库, 就需要下载对应的Driver, 然后在DriverManager中注册, 之后操作JDBC API就可以了.
JDBC和DriverManager类, Driver接口都在java.sql包中, 而具体的Driver类实现, 则由各个数据库厂商进行实现.
还有一些关键的接口如下:
Connection
接口, 表示数据库连接Statement
接口, SQL语句对象, 负责生成和执行SQL语句PreparedStatement
接口, 预处理的SQL语句CallableStatment
接口, 负责执行存储过程ResultSet
接口, 表示返回的结果集, SQL语句对象执行完毕之后就会返回这种类型
来详细的看使用方法.
示例
这两个类(接口)是紧密配合工作的, 在使用任何数据库之前, 都要获得驱动, 然后通过DriverManager.registerDriver(Driver)来注册驱动.
使用Class.forName()
来加载驱动, 实际上就不用新建对象, 是为了解耦, 实际加载驱动的模块在驱动的静态块中.
要使用MySQL, 可以下载官方的Connector驱动, 然后就可以注册驱动了. 完整示例如下:
public static void main(String[] args) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.cj.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/BookDB?useUnicode=true&characterEncoding=UTF-8", "root", "fflym0709"); Statement statement = connection.createStatement(); String sql = "SELECT * FROM BOOKS"; ResultSet rs = statement.executeQuery(sql); while (rs.next()) { System.out.print(rs.getString(1)+"|"); System.out.print(rs.getString(2)+"|"); System.out.print(rs.getString(3)+"|"); System.out.print(rs.getBigDecimal(4)+"|"); System.out.print(rs.getDate(5).toLocalDate().getYear()+"|"); System.out.print(rs.getString(6)+"|"); System.out.println(rs.getInt(7)+"|"); } //关闭的时候逆向关闭 rs.close(); statement.close(); connection.close(); }
ResultSet的每一个元素代表一个查询的结果, 可以按照表的栏数取出其中的对象, 这里还需要知道MySQL与Java类中的对应关系.
事务处理
默认将一条语句视为一个事务, 可以关闭, 然后手工使用.commit()和.rollback():
public class TestJDBC { public static void main(String[] args) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.cj.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/BookDB?useUnicode=true&characterEncoding=UTF-8", "root", "********"); Statement statement = connection.createStatement(); connection.setAutoCommit(false); try { statement.execute("UPDATE BOOKS SET SALE_AMOUNT=SALE_AMOUNT+10 WHERE ID='103'"); statement.execute("UPDATE BOOKS SET SALE_AMOUNT=SALE_AMOUNT+10 WHERE ID='102'"); statement.execute("UPDATE BOOKS SET PRICE=79.5 WHERE ID='102'"); connection.commit(); } catch (Exception e) { e.printStackTrace(); connection.rollback(); } statement.close(); connection.close(); } }
JNDI数据库连接
每次都创建连接, 太重型, 在上次的学习里了解过了第三方库的连接池, 现在来看看如何在Web容器中配置DataSource.
数据源由Web容器来提供可以非常方便的供Web应用来使用. Java程序可以通过JNDI技术, 通过javax.naming包来检索对象并且使用. Tomcat可以把DataSource配置成一种JNDI资源.
先来看看如何配置, 需要两个配置, 一个是配置context.xml 这个属于tomcat的配置, 还一个是配置web.xml这个属于web应用的配置. 至于context.xml的位置也有讲究, 这里就只在/conf/下直接配置用于整个Web容器的context.xml:
<Context> ...... <WatchedResource>WEB-INF/web.xml</WatchedResource> <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> <Resource name="jdbc/bookDB" type="javax.sql.DataSource" password="fflym0709" driverClassName="com.mysql.cj.jdbc.Driver" maxIdle="5" maxWait="5000" username="root" url="jdbc:mysql://localhost:3306/BookDB?useUnicode=true&characterEncoding=UTF-8" maxActive="10"/> ...... </Context>
如此配置之后, 容器的环境中就有了一个叫做jdbc/bookDB
的名称的对象, 不过还需要在web-xml中也配置一下:
<resource-ref> <res-ref-name>jdbc/bookDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
这样就能被当前应用识别了, 其中的名称和对应的类型都要和context.xml中保持一致.
之后在程序中, 通过 javax.naming类来查找对象并使用:
Context context = new InitialContext(); DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/bookDB"); Connection connection = dataSource.getConnection();
橙色部分是必须加上去的, 红色部分就是刚才自己定义的名称, 通过这个名称查找可以得到一个对象, 由于已经知道是DataSource对象, 就可以实行强制转换, 然后直接获取连接就可以了.
和其他的连接池库一样, 获取的connection实际上是一个Connection的代理类,对其调用.close()是归还进池子里.
使用数据源的还一个好处就是会自动关闭由MySQL驱动程序运行的Abandoned Connection Cleanup Thread 线程. 否则在退出Web应用的时候可以看到这个线程没有被终止, 会报错.
断更好久,不知道博主忙啥了.双十一战绩如何.
哈哈,感谢一直关注博客,11月头上智齿犯了, 上周六去拔了个牙,到昨天刚刚消肿….