详解JDBC使用

什么是JDBC

JDBC(Java Database Connectivity),即Java数据库连接,是一种用于执行SQL语句的Java API,可以为多种关系数据库提供同一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,根据这种基准可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。总而言之,JDBC做了三件事:

1、与数据库建立连接

2、发送操作数据库的语句

3、处理结果

JDBC简单示例

下面的代码演示了如何利用JDBC从数据库中查询若干条符合要求的数据出来,使用的数据库是MySql。

1、建立一个数据库和一张表,我的习惯是在CLASSPATH底下建立一个.sql的文件用于存放sql语句

create database school;

use school;

create table student
(
  studentId      int         primary key  auto_increment  not null,
  studentName    varchar(10)                              not null,
  studentAge    int,
  studentPhone  varchar(15)
)

insert into student values(null,'Betty', '20', '00000000');
insert into student values(null,'Jerry', '18', '11111111');
insert into student values(null,'Betty', '21', '22222222');
insert into student values(null,'Steve', '27', '33333333');
insert into student values(null,'James', '22', '44444444');
commit;

2、建立一个.properties文件用于存储MySql连接的几个属性。为什么要建立.properties而不在代码里面写死,由于这个并不是Java设计模式的分类,就不细讲了,只需要记住:从设计的角度看,把内容写在配置文件中永远好过把内容写死在代码中。

mysqlpackage=com.mysql.jdbc.Driver
mysqlurl=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8
mysqlname=root
mysqlpassword=root

3、根据表字段建立实体类

public class Student
{
  private int    studentId;
  private String  studentName;
  private int    studentAge;
  private String  studentPhone;

  public Student(int studentId, String studentName, int studentAge,
      String studentPhone)
  {
    this.studentId = studentId;
    this.studentName = studentName;
    this.studentAge = studentAge;
    this.studentPhone = studentPhone;
  }

  public int getStudentId()
  {
    return studentId;
  }

  public String getStudentName()
  {
    return studentName;
  }

  public int getStudentAge()
  {
    return studentAge;
  }

  public String getStudentPhone()
  {
    return studentPhone;
  }

  public String toString()
  {
    return "studentId = " + studentId + ", studentName = " + studentName + ", studentAge = " +
        studentAge + ", studentPhone = " + studentPhone;
  }
}

4、写一个DBConnection类专门用于向外提供数据库连接。我这里用了MySql,所以只有一个mysqlConnection,如果还用到了Oracle,当然还可以向外提供一个oracleConnection。把这些连接设为全局的可能有人会想是否会有线程安全问题,这是一个很好的问题。那因为我们只从Connection里面读取一个PreparedStatement出来,而不会去写它,只读不修改,是不会引发线程安全问题的。另外把Connection设置为static的保证了Connection在内存中只有一份,不会占多大资源,每次使用完不调用close()方法去关闭它也没事。

public class DBConnection
{
  private static Properties properties = new Properties();

  static
  {
    /** 要从CLASSPATH下取.properties文件,因此要加"/" */
    InputStream is = DBConnection.class.getResourceAsStream("/db.properties");
    try
    {
      properties.load(is);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  /** 这个mysqlConnection只是为了用来从里面读一个PreparedStatement,不会往里面写数据,因此没有线程安全问题,可以作为一个全局变量 */
  public static Connection mysqlConnection = getConnection();

  public static Connection getConnection()
  {
    Connection con = null;
    try
    {
      Class.forName((String)properties.getProperty("mysqlpackage"));
      con = DriverManager.getConnection((String)properties.getProperty("mysqlurl"),
          (String)properties.getProperty("mysqlname"),
          (String)properties.getProperty("mysqlpassword"));
    }
    catch (ClassNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (SQLException e)
    {
      e.printStackTrace();
    }
    return con;
  }
}

5、建立一个工具类,用来写各种方法,专门和数据库进行交互。这种工具类最好搞成单例的,这样就不用每次去new出来了(实际上new出来也没看出来会有什么好处),节省资源

package com.xrq.test11;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class StudentManager
{
  private static StudentManager instance = new StudentManager();

  private StudentManager()
  {

  }

  public static StudentManager getInstance()
  {
    return instance;
  }

  public List<Student> querySomeStudents(String studentName) throws Exception
  {
    List<Student> studentList = new ArrayList<Student>();
    Connection connection = DBConnection.mysqlConnection;
    PreparedStatement ps = connection.prepareStatement("select * from student where studentName = ?");
    ps.setString(1, studentName);
    ResultSet rs = ps.executeQuery();

    Student student = null;
    while (rs.next())
    {
      student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4));
      studentList.add(student);
    }

    ps.close();
    rs.close();
    return studentList;
  }
}

6、写个main函数去调用一下

List<Student> studentList = new ArrayList<Student>();
    studentList = StudentManager.getInstance().querySomeStudents("Betty");
    for (Student student : studentList)
      System.out.println(student);

7、看一下运行结果,和数据库里面的一样,成功

studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000
studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222 

为什么要使用占位符"?"

看一下第5点,大家一定注意到了,写sql语句的时候用了"?"占位符,当然有美化代码的因素,不用占位符就要在括号里写"+"来拼接参数,如果要拼接的参数一多,代码肯定不好看,可读性不强。但是除了这个原因,还有另外一个重要的原因,就是避免一个安全问题。假设我们不用占位符写sql语句,那"querySomeStudents(String name) throws Exception"方法就要这么写:

public List<Student> querySomeStudents(String studentName) throws Exception
{
  List<Student> studentList = new ArrayList<Student>();
  Connection connection = DBConnection.mysqlConnection;
  PreparedStatement ps = connection.prepareStatement("select * from student where studentName = '" + studentName + "'");
  ResultSet rs = ps.executeQuery();

  Student student = null;
  while (rs.next())
  {
    student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4));
    studentList.add(student);
  }

  ps.close();
  rs.close();
  return studentList;
}

上面的main函数一样可以获取到两条数据,但是问题来了,如果我这么调用呢:

public static void main(String[] args) throws Exception
  {
    List<Student> studentList = new ArrayList<Student>();
    studentList = StudentManager.getInstance().querySomeStudents("' or '1' = '1");
    for (Student student : studentList)
      System.out.println(student);
  }

看下运行结果:

studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000
studentId = 2, studentName = Jerry, studentAge = 18, studentPhone = 11111111
studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222
studentId = 4, studentName = Steve, studentAge = 27, studentPhone = 33333333
studentId = 5, studentName = James, studentAge = 22, studentPhone = 44444444

为什么?看下拼接之后的sql语句就知道了:

select * from student where studentName = '' or '1' = '1'

'1'='1'永远成立,所以前面的查询条件是什么都没用。这种问题是有应用场景的,不是随便写一下。Java越来越多的用在Web上,既然是Web,那么查询的时候有一种情况就是用户输入一个条件,后台获取到查询条件,拼接sql语句查数据库,有经验的用户完全可以输入一个"‘'' or '1' = '1",这样就拿到了库里面的所有数据了。

JDBC事物

谈数据库必然离不开事物,事物简单说就是"要么一起成功,要么一起失败"。那简单往前面的StudentManager里面写一个插入学生信息的方法:

public void addStudent(String studentName, int studentAge, String studentPhone) throws Exception
{
  Connection connection = DBConnection.mysqlConnection;
  PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)");
  ps.setString(1, studentName);
  ps.setInt(2, studentAge);
  ps.setString(3, studentPhone);
  if (ps.executeUpdate() > 0)
    System.out.println("添加学生信息成功");
  else
    System.out.println("添加学生信息失败");
}
public static void main(String[] args) throws Exception
{
  StudentManager.getInstance().addStudent("Betty", 17, "55555555");
}

运行就不运行了,反正最后结果是"添加学生信息成功",数据库里面多了一条数据。注意一下:

1、增删改用的是executeUpdate()方法,因为增删改认为都是对数据库的更新

2、查询用的是executeQuery()方法,看名字就知道了"Query",查询嘛

可能有人注意到一个问题,就是Java代码在insert后并没有对事物进行commit,数据就添加进数据库了,也能查出来,这是为什么呢?因为JDK的Connection设置了事物的自动提交。如果在addStudent(...)方法里面这么写:

Connection connection = DBConnection.mysqlConnection;
connection.setAutoCommit(false);

autoCommit这个属性原来是true,JDK自然会帮助开发者自动提交事物了。OK,如果要改成手动提交事物的代码,那么应该这么写addStudent(...)方法:

public void addStudent(String studentName, int studentAge, String studentPhone) throws Exception
{
  Connection connection = DBConnection.mysqlConnection;
  connection.setAutoCommit(false);
  PreparedStatement ps = connection.prepareStatement("insert into student values(null,?,?,?)");
  ps.setString(1, studentName);
  ps.setInt(2, studentAge);
  ps.setString(3, studentPhone);
  try
  {
    ps.executeUpdate();
    connection.commit();
  }
  catch (Exception e)
  {
    e.printStackTrace();
    connection.rollback();
  }
}

要记得抛异常的时候利用rollback()方法回滚掉事物。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • java中JDBC实现往MySQL插入百万级数据的实例代码

    想往某个表中插入几百万条数据做下测试,原先的想法,直接写个循环10W次随便插入点数据试试吧,好吧,我真的很天真.... DROP PROCEDURE IF EXISTS proc_initData;--如果存在此存储过程则删掉 DELIMITER $ CREATE PROCEDURE proc_initData() BEGIN DECLARE i INT DEFAULT 1; WHILE i<=100000 DO INSERT INTO text VALUES(i,CONCAT('姓名',i),

  • sqlserverdriver配置方法 jdbc连接sqlserver

    一.下载驱动程序. 下载地址:http://download.microsoft.com/download/8/B/D/8BDABAE2-B6EA-41D4-B903-7916EF3690EF/sqljdbc_1.2.2323.101_enu.exe 首先下载到sql2005jdbc驱动sqljdbc_2.0.1008.2_enu.exe(版本号1.1之后都支持sql2005,2.0的支持sql2008) 下载的是一个解压就可以使用的,不需要要安装,你可以把这个包放在任何你想要放的地方,比如说你

  • Java使用JDBC连接数据库的实现方法

    本文实例讲述了Java使用JDBC连接数据库的实现方法,是Java数据库程序设计里非常实用的重要技巧.分享给大家供大家参考.具体如下: JDBC(Java Data Base Connectivity)数据库连接,通常我们在编写web应用或java应用程序要连接数据库时就要使用JDBC.使用JDBC连接数据库一般步骤有: 1.加载驱动程序 Class.forName(driver); 2.创建连接对象 Connection con = DriverManager.getConnection(ur

  • JDBC 程序的常见错误及调试方法

    数据库:MySQL 在编写应用的时候,为了调试程序方便,可以在异常处理代码中把异常信息显示出来,这样可以根据错误提示调试代码.异常处理代码通常可以写成这样: try{ - }catch(Exception e){ System.out.println(e.toString()); } 下面是一些常见的错误信息: (1)驱动程序不存在 提示的错误信息如下: java.lang.ClassNotFoundException: com.mysql.jdbc.Drive 后半部分是您在程序中写的驱动程序

  • MyEclipse通过JDBC连接MySQL数据库基本介绍

    1.前提是MyEclipse已经能正常开发Java工程 2.安装MySQL 个人使用的是版本是 mysql-5.0.22-win32.zip 网址:http://www.mysql.com/downloads/mysql/#downloads 3.下载JDBC驱动 个人使用的是 mysql-connector-java-5.1.22.zip,所需要的就是解压缩之后其中的 mysql-connector-java-5.1.22-bin.jar 网址:http://www.mysql.com/dow

  • 详解poi+springmvc+springjdbc导入导出excel实例

    工作中常遇到导入导出excel的需求,本獂有一简答实例与大家分享. 废话不多说, 1.所需jar包: 2.前端代码: ieport.jsp: <%@page import="java.util.Date"%> <%@ page language="java" contentType="text/html; charset=utf-" pageEncoding="utf-"%> <!DOCTYPE

  • jsp+servlet+jdbc实现对数据库的增删改查

    一.JSP和Servlet的简单介绍 1.Servlet和JSP简介: Java开发Web应用程序时用到的技术主要有两种,即Servlet和JSP,Servlet是在服务器端执行的Java程序,一个被称为Servlet容器的程序(其实就是服务器) 负责执行Java程序,而JSP(Java Server Page)则是一个页面, 由JSP容器负责执行. 2.Servlet和JSP的区别: Servlet以Java程序为主, 输出HTML代码时需要使用out.println函数,也就是说Java中内

  • Java开发Oracle数据库连接JDBC Thin Driver 的三种方法

    Oracle的jdbc驱动三种主要分类: 1.JDBC OCI: oci是oracle call interface的缩写,此驱动类似于传统的ODBC 驱动.因为它需要Oracle Call Interface and Net8,所以它需要在运行使用此驱动的JAVA程序的机器上安装客户端软件,其实主要是用到orcale客户端里以dll方式提供的oci和服务器配置. 2.JDBC Thin: thin是for thin client的意思,这种驱动一般用在运行在WEB浏览器中的JAVA程序.它不是

  • Spring 数据库连接池(JDBC)详解

    数据库连接池 对一个简单的数据库应用,由于对数据库的访问不是很频繁,这时可以简单地在需要访问数据库时,就新创建一个连接,就完后就关闭它,这样做也不会带来什么性能上的开销.但是对于一个复杂的数据库应用,情况就完全不同而,频繁的建立.关闭连接,会极大地减低系统的性能,因为对于连接的使用成了系统性能的瓶颈. 通过建立一个数据库连接池以及一套连接使用管理策略,可以达到连接复用的效果,使得一个数据库连接可以得到安全.高效的复用,避免了数据库连接频繁建立.关闭的开销. 数据库连接池的基本原理是在内部对象池中

  • 基于Java回顾之JDBC的使用详解

    尽管在实际开发过程中,我们一般使用ORM框架来代替传统的JDBC,例如Hibernate或者iBatis,但JDBC是Java用来实现数据访问的基础,掌握它对于我们理解Java的数据操作流程很有帮助. JDBC的全称是Java Database Connectivity. JDBC对数据库进行操作的流程:•连接数据库•发送数据请求,即传统的CRUD指令•返回操作结果集JDBC中常用的对象包括:•ConnectionManager•Connection•Statement•CallableStat

随机推荐