JDBC详解
JDBC简介
JDBC(Java DataBase Connectivity),是Java和数据库连接的桥梁,是一个规范而不是实现,能够执行sql语句。它由一组用Java语言编写的类和接口组成。
各个不同类型的数据库都有相应的实现。本文中的代码都是针对MySql数据库实现的。
JDBC流程简介
- 创建一个简单的Java项目,通过build path导入连接数据库的jar包
![]()
- 初始化驱动类Driver
Class.forName("com.mysql.jdbc.Driver");
Class.forName的作用是加载和初始化类Driver,返回的是一个类对象。
- 通过DriverManager创建与数据库之间的一个连接
conn= DriverManager.getConnection("jdbc:mysql:///jdbc_demo01?characterEncoding=UTF-8", "root","Cpic1234");
第一个参数是连接数据库的地址,第二个参数是用户名,第三个参数是密码。
- 通过连接创建Statement或者PreparedStatement
Statement s=conn.createStatement();
它们的作用都是执行sql语句。这里创建的是Statement,平时很少用到Statement,基本上用的都是PrepareStatement,至于为什么后面会讲到。
- 写sql语句,用execute方法执行
String sql="insert into student values(1,"+"'九儿'"+"'男')";
s.execute(sql);
这里可以看出,Statement执行的sql语句是多段字符串拼接而成的,代码看着很费劲。
- 释放资源
s.close();
conn.close();
这里要注意,释放资源的顺序是从里到外。
以上是使用JDBC整体的一个流程,下面对增删改查,资源释放,Statement和PreparedStatement之间的区别做一个详细介绍。
JDBC编程详解
- 插入
//增加学员 public static void add() { String sql="insert into student values(?,?,?)"; Connection conn=null; PreparedStatement ps=null; conn=Dbutil.getConnection(); try { ps=conn.prepareStatement(sql); ps.setInt(1, 2); ps.setString(2, "牛皮"); ps.setString(3, "男"); ps.executeUpdate(); ps.close(); conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
- 修改
//修改学员信息 public static void update() { String sql="update student set sname=? where sid=?"; Connection conn=null; PreparedStatement ps=null; conn=Dbutil.getConnection(); try { ps=conn.prepareStatement(sql); ps.setString(1, "学渣"); ps.setInt(2, 2); ps.executeUpdate(); ps.close(); conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
- 删除
//删除学员 public static void delete() { String sql="delete from student"; Connection conn=null; PreparedStatement ps=null; conn=Dbutil.getConnection(); try { ps=conn.prepareStatement(sql); //ps.setInt(1, 1); ps.executeUpdate(); ps.close(); conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
以上是增删改操作,通过代码可以发现,出了sql语句有区别,其他都一样。上面代码有个缺点,释放资源的代码重复出现。我们可以优化下代码,方法是写一个工具类Dbutil。具体代码如下
public class Dbutil { /** * 取得数据库的连接 * @return 数据库的一个链接 */ public static Connection getConnection() { Connection conn=null; try { Class.forName("com.mysql.jdbc.Driver"); conn= DriverManager.getConnection("jdbc:mysql:///jdbc_demo01?characterEncoding=UTF-8", "root","Cpic1234"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param rs * @param ps * @param conn */ public static void closeAll(ResultSet rs,PreparedStatement ps,Connection conn) { try { rs.close(); ps.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
这样可以通过Dbutil.getConnection()方法获取一个Connection对象,事务执行完毕,再调用Dbutil.closeAll()将资源释放。
- 查询
//查询 public static List<Student> find(){ List<Student>list=new ArrayList<Student>(); String sql="select * from student "; Connection conn=null; PreparedStatement ps=null; conn=Dbutil.getConnection(); try { ps=conn.prepareStatement(sql); ResultSet rs=ps.executeQuery();
if(rs!=null){ while(rs.next()) { Student stu=new Student(); stu.setSid(rs.getInt("sid")); stu.setSname(rs.getString("sname")); stu.setSex(rs.getString("sex").toCharArray()[0]); list.add(stu); }
} Dbutil.closeAll(rs, ps, conn); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; }
调用executeQuery()返回的是结果集ResultSet。必须先检查值为Null的情况,否则后面可能会有报空指针异常的情况。
首先用while(rs.next())遍历结果集,循环体内用rs.getInt("sid")获取一条学生记录的sid,rs.getString("sname"),rs.getString("sex")获取一条学生记录的sname和sex。
然后我们就可以把这些值复制给一个具体的对象new Student();
当然,也可以用getInt(1)通过下标的方式取值,但不建议这么做,因为如果数据库表结构发生改变就会报错。
Statement和PreparedStatement的区别
- 都可以执行sql。Statement需要拼接sql语句,如果是复杂的sql语句,很容易写错,看代码也费劲。PreparedStatement根据sql创建,sql语句使用占位符,语句结构已经事先定义好。
- Statement没执行一次sql,都要重新编译一次;PreparedStatement使用预编译机制,大大提高了运行效率。
- Statement有sql注入的风险;PreparedStatement因为已经定义好了sql的语句结构,大大降低了sql注入的风险。

浙公网安备 33010602011771号