JDBC(JavaDataBase Connectivity)就是Java数据库链接,说白了就是用Java语言来操做数据库。原来咱们操做数据库是在控制台使用SQL语句来操做数据库,JDBC是用Java语言向数据库发送SQL语句。java
早期SUN公司的天才们想编写一套能够链接天下全部数据库的API,可是当他们刚刚开始时就发现这是不可完成的任务,由于各个厂商的数据库服务器差别太大了。后来SUN开始与数据库厂商们讨论,最终得出的结论是,由SUN提供一套访问数据库的规范(就是一组接口),并提供链接数据库的协议标准,而后各个数据库厂商会遵循SUN的规范提供一套访问本身公司的数据库服务器的API出现。SUN提供的规范命名为JDBC,而各个厂商提供的,遵循了JDBC规范的,能够访问本身数据库的API被称之为驱动!
JDBC是接口,而JDBC驱动才是接口的实现,没有驱动没法完成数据库链接!每一个数据库厂商都有本身的驱动,用来链接本身公司的数据库。
固然还有第三方公司专门为某一数据库提供驱动,这样的驱动每每不是开源免费的!mysql
import org.junit.Test; import java.sql.*; public class TestJDBC { @Test //基本查询语句d public void statement() throws Exception { //驱动 String driver ="com.mysql.jdbc.Driver"; Class.forName(driver); //数据库连接 String url ="jdbc:mysql://localhost:3306/jtdb"; Connection cn = DriverManager.getConnection(url,"root","1234"); //获得语句对象,它来执行sql语句 Statement stat = cn.createStatement(); //建立语句对象 //查询返回结果集 resultset String sql = "select * from dept"; ResultSet rs = stat.executeQuery(sql); //执行查询的语句 //打印数据库表元数据,列名,dept字段数 int cols = rs.getMetaData().getColumnCount(); for(int i = 1 ; i <= cols ; i++ ){ System.out.print(rs.getMetaData().getColumnName(i)+"\t"); } System.out.println();//换行 //打印表中数据 while(rs.next()){ for(int i =1 ; i<=cols ;i++){ //rs.getString(i); //获取第几列值,返回字符串类型 System.out.print(rs.getString(i)+"\t"); } System.out.println(); //每一条数据打印完毕换行 } } @Test //预编译查询语句 public void prepareStatment() throws Exception { String driver ="com.mysql.jdbc.Driver"; //驱动 String url = "jdbc:mysql://localhost:3306/jtdb"; //连接 //预编译sql中用?做为占位符,未来会被真实值替换掉 String sql = "select * from dept where deptno = ?" ; Class.forName(driver); Connection cn = DriverManager.getConnection(url,"root","1234"); //获取连接 //带参数 PreparedStatement ps = cn.prepareStatement(sql); //返回预编译对象 ps.setString(1,"3"); //参数1:指?的位置 可能有多个;参数2:是参数值 //查询 ResultSet rs =ps.executeQuery(); int cols = rs.getMetaData().getColumnCount(); //列的总数 for (int i = 1 ; i <= cols ; i++){ //打印列的名称 System.out.print(rs.getMetaData().getColumnName(i)+"\t"); } //打印数据 while(rs.next()){//每次向下取一条,直到结尾 System.out.println();//换行 for(int i = 1 ; i <= cols ; i++){ System.out.print(rs.getString(i)+"\t"); } } } }
驱动程序管理器是负责管理驱动程序的,驱动注册之后,会保存在DriverManager中的已注册列表中后续的处理就能够对这个列表进行操做。sql
Class.forName("com.mysql.jdbc.Driver");//加载驱动
在JDBC中链接被抽象为Connection的链接对象数据库
DriverManager.getConnection(url,username,password)
用于执行不带参数的简单 SQL 语句,每次执行 SQL语句,数据库都要执行 SQL 语句的编译c#
Statement stat = connection.createStatement();
prepareStatement与Statement的区别
一、Statement用于执行静态SQL语句,在执行时,必须指定一个事先准备好的SQL语句。
二、PrepareStatement是预编译的SQL语句对象,sql语句被预编译并保存在对象中。被封装的sql语句表明某一类操做,语句中能够包含动态参数“?”,在执行时能够为“?”动态设置参数值。
三、使用PrepareStatement对象执行sql时,sql被数据库进行解析和编译,而后被放到命令缓冲区,每当执行同一个PrepareStatement对象时,它就会被解析一次,但不会被再次编译。在缓冲区能够发现预编译的命令,而且能够重用。
四、PrepareStatement能够减小编译次数提升数据库性能。服务器
当咱们查询数据库时,返回的是一个二维的结果集,咱们这时候须要使用 ResultSet 来遍历结果集,获取每一行的数据。多线程
ResultSet rs = stat.executeQuery(sql);
数据库链接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤其突出。 一个数据库链接对象均对应一个物理数据库链接,每次操做都打开一个物理链接,使用完都关闭链接,这样形成系统的性能低下。
数据库链接池的解决方案是在应用程序启动时创建足够的数据库链接,并讲这些链接组成一个链接池(简单说:在一个“池”里放了好多半成品的数据库链接对象),由应用程序动态地对池中的链接进行申请、使用和释放。对于多于链接池中链接数的并发请求,应该在请求队列中排队等待。而且应用程序能够根据池中链接的使用率,动态增长或减小池中的链接数。
链接池技术尽量多地重用了消耗内存地资源,大大节省了内存,提升了服务器地服务效率,可以支持更多的客户服务。经过使用链接池,将大大提升程序运行效率,同时,咱们能够经过其自身的管理机制来监视数据库链接的数量、使用状况等。
并发
链接池相似于线程池或者对象池,数据库链接池为系统的运行带来如下优点:性能
第1、链接池的创建。
通常在系统初始化时,链接池会根据系统配置创建,并在池中建立了几个链接对象,以便使用时能从链接池中获取。链接池中的链接不能随意建立和关闭,这样避免了链接随意创建和关闭形成的系统开销。
Java中提供了不少容器类能够方便的构建链接池,例如Vector、Stack等。url
第2、链接池的管理。
链接池管理策略是链接池机制的核心,链接池内链接的分配和释放对系统的性能有很大的影响。其管理策略是:
当客户请求数据库链接时,首先查看链接池中是否有空闲链接,若是存在空闲链接,则将链接分配给客户使用;若是没有空闲链接,则查看当前所开的链接数是否已经达到最大链接数,若是没达到就从新建立一个链接给请求的客户;若是达到就按设定的最大等待时间进行等待,若是超出最大等待时间,则抛出异常给客户。
当客户释放数据库链接时,先判断该链接的引用次数是否超过了规定值,若是超过就从链接池中删除该链接,不然保留为其余客户服务。
该策略保证了数据库链接的有效复用,避免频繁的创建、释放链接所带来的系统资源开销。
第3、链接池的关闭。
当应用程序退出时,关闭链接池中全部的链接,释放链接池相关的资源,该过程正好与建立相反。
一、并发问题
为了使链接管理服务具备最大的通用性,必须考虑多线程环境,即并发问题。
这个问题相对比较好解决,由于各个语言自身提供了对并发管理的支持像java,c#等等,使用synchronized(java)lock(C#)关键字便可确保线程是同步的。
二、事务处理
咱们知道,事务具备原子性,此时要求对数据库的操做符合“ALL-OR-NOTHING”原则,即对于一组SQL语句要么全作,要么全不作。
咱们知道当2个线程共用一个链接Connection对象,并且各自都有本身的事务要处理时候,对于链接池是一个很头疼的问题,由于即便Connection类提供了相应的事务支持,但是咱们仍然不能肯定那个数据库操做是对应那个事务的,这是因为咱们有2个线程都在进行事务操做而引发的。
为此咱们可使用每个事务独占一个链接来实现,虽然这种方法有点浪费链接池资源可是能够大大下降事务管理的复杂性。
三、链接池的分配与释放
链接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,能够提升链接的复用度,从而下降创建新链接的开销,同时还能够加快用户的访问速度。
对于链接的管理可以使用一个List。即把已经建立的链接都放入List中去统一管理。每当用户请求一个链接时,系统检查这个List中有没有能够分配的链接。若是有就把那个最合适的链接分配给他,若是没有就抛出一个异常给用户。
4、链接池的配置与维护链接池中到底应该放置多少链接,才能使系统的性能最佳?系统可采起设置最小链接数(minConnection)和最大链接数(maxConnection)等参数来控制链接池中的链接。比方说,最小链接数是系统启动时链接池所建立的链接数。若是建立过多,则系统启动就慢,但建立后系统的响应速度会很快;若是建立过少,则系统启动的很快,响应起来却慢。这样,能够在开发时,设置较小的最小链接数,开发起来会快,而在系统实际使用时设置较大的,由于这样对访问客户来讲速度会快些。最大链接数是链接池中容许链接的最大数目,具体设置多少,要看系统的访问量,可经过软件需求上获得。如何确保链接池中的最小链接数呢?有动态和静态两种策略。动态即每隔必定时间就对链接池进行检测,若是发现链接数量小于最小链接数,则补充相应数量的新链接,以保证链接池的正常运转。静态是发现空闲链接不够时再去检查。