连接数据库的方式:
第一种方式:ODBC:开放数据库连接是微软公司开放服务结构中有关数据库的一个组成部分,是数据库访问接口标准。ODBC是基于C语言实现的。提供了语言和数据库进行交互的一致性的接口,便于语言和数据库通信以及语言对数据库的各种操作。
第二种方式:JDBC(本章重点)
在Java中,数据库存取技术可分为如下几类:
第一种:JDBC直接访问数据库
第二种 :JDO技术(Java Data Object)
第三种:第三方O/R工具,如Hibernate, Mybatis 等
JDBC是java访问数据库的基石,JDO, Hibernate等只是更好的封装了JDBC。
什么是JDBC?
JDBC: Java Data Base Connectivity(java数据库连接)
它是sun公司提供的一套java应用程序访问数据库的技术或规范。是一种用于执行SQL语句的Java API,它统一和规范了应用程序与数据库的连接、执行SQL语句,并到得到返回结果等各类操作,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
JDBC的好处
1、减少了开发程序员的压力,不用去记多套API
2、提高了维护性
如何使用?
第一步:导入jar包:
1.使用JDBC操作数据库,需要导入JDBC的驱动包:mysql-connector-java-5.1.36-bin.jar。
2.在项目下新建libs文件夹,将jar包复制到libs文件夹下面
注意:如果是Dynamic Web Project(动态的web项目)话,则是把驱动jar放到WebContent(有的开发工具叫WebRoot)目录中的WEB-INF目录中的lib目录下即可
3.右键–>Build Path–>Add to Build Path,这时,我们可以在项目的引用包中看到我们引用的jar包.
第二步:Java应用程序访问数据库的过程:
①装载数据库驱动程序;
MySQL的驱动下载地址:http://dev.mysql.com/downloads/
加载驱动:把驱动类加载到内存
注册驱动:把驱动类的对象交给DriverManager管理,用于后面创建连接等使用。
第一种方式:DriverManager.registerDriver(new Driver());//不建议使用
第二种方式: Class.forName(“com.mysql.jdbc.Driver”);//通过反射,加载与注册驱动类,解耦合(不直接依赖)
②通过JDBC建立数据库连接;
③访问数据库,执行SQL语句;
④断开数据库连接。
java.sql包
javax.sql包
此类用于演示JDBC使用的简单步骤
/** * 此类用于演示JDBC使用的简单步骤 * 前提: * ①需要将mysql-connector-java-5.1.37-bin.jar复制到项目的libs目录 * ②右击mysql-connector-java-5.1.37-bin,Build Path——Add To buildPath * */ public class TestConnection { public static void main(String[] args) throws SQLException { // 1.加载驱动(准备工作) DriverManager.registerDriver(new Driver()); // 2.获取连接 /* * 参数1:url * 格式:jdbc:mysql://主机名:端口号/库名 * 参数2:用户名 * 参数3:密码 */ Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/customersDB", "root", "root"); // 3.执行增删改查★ //①获取执行sql语句的命令对象 Statement statement = connection.createStatement(); //②执行sql语句 int update = statement.executeUpdate("delete from customers where id=2"); //③处理结果 System.out.println(update>0?"success":"failure"); // 4.关闭连接 statement.close(); connection.close(); } }
PreparedStatement的使用
/** * 一、向customers表中插入数据,效果如下: 请输入编号:55 请输入姓名:上官红 请输入邮箱:shangguan@126.com 请输入生日(要求按xxxx-xx-xx格式):1988-11-11 插入成功! */ public class TestPreparedStatementByUtils { //增删改 @Test public void test1() throws Exception { Scanner input = new Scanner(System.in); System.out.println("请输入编号:"); int id = input.nextInt(); System.out.println("请输入姓名:"); String name = input.next(); System.out.println("请输入邮箱:"); String email = input.next(); System.out.println("请输入生日:"); String birth = input.next(); //-----------------------------连接数据库的步骤----------------- //1.获取连接 Connection connection = JDBCUtils.getConnection(); //2、执行插入 PreparedStatement statement = connection.prepareStatement("insert into customers values(?,?,?,?,null)"); statement.setInt(1, id); statement.setString(2, name); statement.setString(3, email); statement.setString(4, birth); int update = statement.executeUpdate(); System.out.println(update>0?"插入成功":"插入失败"); //3.关闭 JDBCUtils.close(null, statement, connection); } //查询 @Test public void test2() throws Exception { // 请输入编号:1 // --------------------------------------------------------------------------------- // 编号 姓名 邮箱 生日 // 1 汪峰 wf@126.com 2010-2-2 Scanner input = new Scanner(System.in); System.out.println("请输入编号:"); int id = input.nextInt(); //-----------------------------连接数据库的步骤----------------- //1.获取连接 Connection connection = JDBCUtils.getConnection(); //2、执行查询 PreparedStatement statement = connection.prepareStatement( "select id,name,email,birth from customers where id = ?"); statement.setInt(1, id); ResultSet set = statement.executeQuery(); if(set.next()) { String name = set.getString(2); String email = set.getString(3); String birth = set.getString(4); System.out.println(id+"\t"+name+"\t"+email+"\t"+birth); } //3.关闭 JDBCUtils.close(set, statement, connection); } }
此类用于演示批处理和PreparedStatement与Statement之间的效率问题
/** * 此类用于演示批处理 * 情况1:多条sql语句的批量执行【较少使用】 * Statement+批处理:提高了执行的效率,并没有减少编译的次数 * 情况2:一条sql语句的批量传参【较多使用】 * PreparedStatement+批处理:减少了执行的次数,也减少了编译的次数,大大提高效率 * 相关API: * addBatch() * executeBatch() * clearBatch() * 注意: * ①需要在url添加reWriteBatchedStatement = true * 驱动类使用的版本:5.1.37、5.1.36但不能使用5.1.7(不支持批处理) * ②插入时,使用values,而不是value! *案例:添加50000条管理员记录 */ public class TestBatch { //没有使用批处理 @Test public void testNoBatch() throws Exception { //1.获取连接 Connection connection = JDBCUtils.getConnection(); //2.执行插入 PreparedStatement statement = connection.prepareStatement("insert into admin values(?,?,?)"); for(int i=1;i<=50000;i++) { statement.setInt(1, i); statement.setString(2, "john"+i); statement.setString(3, "0000"); statement.executeUpdate(); } //3.关闭 JDBCUtils.close(null, statement, connection); } //使用批处理 @Test public void testUseBatch() throws Exception { //1.获取连接 Connection connection = JDBCUtils.getConnection(); //2.执行插入 PreparedStatement statement = connection.prepareStatement("insert into admin values(?,?,?)"); for(int i=1;i<=50000;i++) { statement.setInt(1, i); statement.setString(2, "john"+i); statement.setString(3, "0000"); //添加到批处理包(放到框中) statement.addBatch(); if(i%1000==0) { statement.executeBatch();//执行批处理包的sql(将框中的苹果们运到了楼上) statement.clearBatch();//清空批处理包的sql(卸货) } } //3.关闭 JDBCUtils.close(null, statement, connection); } }
Blob类型数据的读写
/** * 此类用于演示Blob类型数据的读写 * 注意:只能使用PreparedStatement实现Blob类型的读写,不能使用Statement * 相关API: * setBlob(占位符索引,InputStream) * InputStream is =getBinaryStream(列索引) */ public class TestBlob { //测试Blob类型数据的写入:修改小苍的照片为指定照片 @Test public void test1() throws Exception { //1.获取连接 Connection connection = JDBCUtils.getConnection(); //2.执行修改 PreparedStatement statement = connection.prepareStatement("update customers set photo = ? where name = ?"); statement.setBlob(1, new FileInputStream("E:\\beauty\\cang.jpg"));//★ statement.setString(2, "小苍"); int update = statement.executeUpdate(); System.out.println(update>0?"插入成功":"插入失败"); //3.关闭 JDBCUtils.close(null, statement, connection); } //测试Blob类型数据的读取:将小苍的图片读取到项目的根目录下 @Test public void test2() throws Exception { //1.获取连接 Connection connection = JDBCUtils.getConnection(); //2.执行查询 PreparedStatement statement = connection.prepareStatement("select photo from customers where name = ?"); statement.setString(1, "小苍"); ResultSet set = statement.executeQuery(); if(set.next()) { // Blob blob = set.getBlob(1); // InputStream binaryStream = blob.getBinaryStream(); InputStream inputStream = set.getBinaryStream(1); FileOutputStream fos = new FileOutputStream("src\\beauty.jpg"); //边读边写:复制图片 byte[] b = new byte[1024]; int len; while((len=inputStream.read(b))!=-1) { fos.write(b, 0, len); } fos.close(); inputStream.close(); } //3.关闭连接资源 JDBCUtils.close(set, statement, connection); } }
##JDBC常用的API
DriverManager驱动管理类 registDriver 加载驱动【不建议使用】 getConnection获取连接【后期往往通过数据库连接池获取】 Connection连接接口 createStatement()获取命令对象 prepareStatement(sql)获取预编译命令对象 close Statement命令对象接口 executeUpdate(sql)执行增删改语句,返回受影响的行数 executeQuery(sql)执行查询语句,返回ResultSet对象 execute(sql)执行任何sql语句,返回是否是结果集 close PreparedStatement预编译命令对象 executeUpdate()执行增删改语句,返回受影响的行数 executeQuery()执行查询语句,返回ResultSet对象 execute()执行任何sql语句,返回是否是结果集 setXX(占位符的索引,占位符的值):设置对应占位符的值为XX类型的变量(索引从1开始) setObject(占位符索引,占位符的值):设置对应占位符的值为Object类型的变量 close ResultSet结果集接口 next()下移一行,指向当前行,返回指向的新行是否有数据 getXX(columnIndex|columnName)根据列索引或列名获取XX类型的值 getObject(columnIndex|columnName)根据列索引或列名获取Object类型的值 previous()上移一行,指向当前行,返回指向的新行是否有数据 close
##德鲁伊连接池的使用
###连接池的好处
1、提高效率
2、提高重用性
3、采用一套统一的管理机制,减少数据库崩溃问题
###数据库连接池的使用
javax.sql包下的DataSource是一个数据库连接池接口。一些开源组织对它进行了实现。
多种开源的数据库连接池:C3P0,DBCP,Druid,BoneCP,Proxool
###德鲁伊使用方式一:
//创建一个数据库连接池 DruidDataSource dds = new DruidDataSource(); //设置连接参数 dds.setUrl("jdbc:mysql://localhost:3306/customersDB"); dds.setUsername("root"); dds.setPassword("root"); dds.setDriverClassName("com.mysql.jdbc.Driver"); //设置池子中的初始化连接数 dds.setInitialSize(5); //设置池子中的最大连接数 dds.setMaxActive(10); //设置池子中的最小连接数 dds.setMinIdle(5); //获取连接 Connection connection = dds.getConnection(); System.out.println("connected!");