需要的jdbc jar 包:
数据持久化分为很多状态
瞬时状态: 保存在内存的程序数据,程序退出后,数据就消失了,称为瞬时状态。
持久化: 将程序数据在瞬时状态和持久状态之间转换的机制。
持久状态: 保存在磁盘上的程序数据,程序退出后依然存在,称为程序数据的持久状态。
数据持久化技术:
Hibernate : hibernate为应用程序提供了高效的O/R关系映射和查询服务,为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架。
JPA : JPA(Java Persistense API)是EJB3.0的一部分,为其提供了一套O/R关系映射的API,但不仅限于EJB中使用,它也可以在web应用或者应用程序客户端中被使用,
甚至在Java桌面程序中被使用。
JDBC : JDBC API是一个Java API,可以访问任何类型的数据库的数据,尤其是存储在关系数据库中的数据。
JDBC 实现数据持久化。
什么是JDBC ?
JDBC 代表Java数据库连接 (Java Database Connectivity) ,它是用于Java编程语言和数据库之间的数据库无关连接的标准Java API ,换句话说 JDBC 是用于在Java 语言编程中与数据库连接的API 。
JDBC 库通常与数据库使用相关,如下面提到的每个任务的API
1 , 连接到数据库。
2, 创建SQL语句
3,在数据库中执行SQL语句查询
4,查看和修改结果记录
常见JDBC组件。
DriverManager: 此类管理数据库驱动程序列表。 使用通信子协议将来自java应用程序的连接请求与适当的数据库驱动程序进行匹配。在JDBC下识别某个子协议的第一个驱动程序将用于建立数据库连接。
Driver: 此接口处理与数据库服务器的通信。我们很少会直接与Driver对象进行交互。 但会使用DriverManager对象来管理这种类型的对象。 它还提取与使用Driver对象相关的信息。
Connection: 此接口具有用于联系数据库的所有方法。 连接(Connection)对象表示通信上下文,即,与数据库的所有通信仅通过连接对象。
Statement:使用从此接口创建的对象将SQL语句提交到数据库。 除了执行存储过程之外,一些派生接口还接受参数。
ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。 它作为一个迭代器并可移动ResultSet对象查询的数据。
SQLException:此类处理数据库应用程序中发生的任何错误
数据库操作 :
//加载驱动
Class.forName( 驱动路径 )
//获取数据库连接
//jdbc:mysql://主机名 : 端口号 / 数据库名
DriverManager . getconnection
Statement 对象。
当获得了与数据库的连接,就可以与数据库进行交互了。JDBC Statement ,CallableStatement 和PreparedStatement 接口定义了可用于发送SQL 或PL/SQL命令。并从数据库接收数据的方法和属性,它们还定义了有助于在Java 和SQL数据类型的数据类型差异转换方法。
利用Statement 对象操作数据库。
PreparedStatement操作数据库
Statement对数据库中的表内容进行增删改操作, 每次增加删除修改都需要加载数据库驱动,连接数据库,执行SQL语句,关闭数据库,这样的话,代码的重复量有些大,代码冗余比较明显,后来进行修改,运用了Java继承封装和多态的思想,对原来的增删改代码进行了优化,在现实的开发中常用PreparedStatement接口而不是Statement接口进行增删改操作:使用PreparedStatement对于代码的可维护性和可读性提高了;使用PreparedStatement尽最大可能提高性能;最重要的一点是极大地提高了安全性。
PreparedStatement是Statement接口的子接口,属于预处理操作,与直接使用Statement不同,PreparedStatement在操作时,是预先在数据表中准备好了一条SQL语句,但是此SQL语句的具体内容暂时不设置,而是之后在进行设置。
PreparedStatement实例包含已编译的SQL语句,SQL语句可能包含1个,2个或多个输入的值,这些值未被明确指定在SQL语句中用?作为占位符代替,之后执行SQL语句之前要用setXXX()方法对值进行写入。
PreparedStatement对象比Statement对象的执行速度要快,因为PreparedStatement对象已经预编译过了,因此需要多次执行的SQL语句也可以用PreparedStatement对象进行执行来加快执行速度。 作为Statement的子类,PreparedStatement接口继承了Statement的所有功能。另外它还整合一整套getXXX()和setXXX()方法,用于对值得获取和输入设置。同时,它还修改了三个方法execute、executeQuery、executeUpdate使它们不需要参数。这些方法的Statement形式,不应该再用于PreparedStatement对象。
常用方法摘要:
executeQuery:
用于产生单个结果集(ResultSet)的语句,例如:被执行最多的SELECT 语句。
这个方法被用来执行 SELECT 语句,但也只能执行查询语句,执行后返回代表查询结果的ResultSet对象。
executeUpdate:
用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。
INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数(int),指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
execute:
可用于执行任何SQL语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。
但它执行SQL语句时比较麻烦,通常我们没有必要使用execute方法来执行SQL语句,而是使用executeQuery或executeUpdate更适合。但如果在不清楚SQL语句的类型时则只能使用execute方法来执行该SQL语句了。
4:getMetaData():获取包含有关ResultSet对象列信息的ResultSetMetaData对象,ResultSet对象将在此执行PreparedStatement对象时返回。
5:getParameterMetaData():获取此PreparedStatement对象的参数的编号、类型和属性。
6:setAsciiStream(int parameterIndex, InputStream x, int longth):将指定参数设置为给定输入流,该输入流将具有给定字节数。
statement、PreparedStatement和CallableStatement区别和联系:
1. Statement、PreparedStatement和CallableStatement都是接口(interface)。
2. Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自PreparedStatement。
3. Statement接口提供了执行语句和获取结果的基本方法;
PreparedStatement接口添加了处理 IN 参数的方法;
CallableStatement接口添加了处理 OUT 参数的方法。
4. a. Statement:
普通的不带参的查询SQL;支持批量更新,批量删除;
b. PreparedStatement:
可变参数的SQL,编译一次,执行多次,效率高;
安全性好,有效防止Sql注入等问题;
支持批量更新,批量删除;
c. CallableStatement:
继承自PreparedStatement,支持带参数的SQL操作;
支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持;
Statement每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形时,效率高于PreparedStatement。
PreparedStatement是预编译的,使用PreparedStatement有几个好处
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
2. 安全性好,有效防止Sql注入等问题。
3. 对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;
4. 代码的可读性和可维护性。
注:
executeQuery:返回结果集(ResultSet),预编译状态下executeQuery( ) 不能传入参数,只有statement 连接对象才能传入参数
executeUpdate: 执行给定SQL语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,
或者不返回任何内容的SQL语句(如 SQL DDL 语句)。
execute: 可用于执行任何SQL语句,返回一个boolean值,
表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。
假设现在有一个本地数据库 localhost 利用java 代码 进行数据库操作;
package com.project.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; import java.sql.CallableStatement; public class JdbcDemo { private static final String url = "jdbc:mysql://localhost:3306/test"; private static final String userName = "root"; private static final String passWord = ""; //初始化驱动,静态代码块 static { try { // 加载驱动 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { JdbcDemo demo = new JdbcDemo(); // 创建一个 Connection 连接对象 通过一个连接对象操作数据库,一个连接多个操作 Connection con = JdbcDemo.getcon(); //demo.updateprepareDemo(con); demo.callableDemo(con); demo.selectDemo(con); JdbcDemo.closeDemo(con); } //调用存储过程 public void callableDemo(Connection con){ //准备SQL String SQL ="{CALL test(?,?,?,?)}"; //创建连接状态 try { CallableStatement state = con.prepareCall(SQL); //设置参数 state.setString(1, "LIDAHU"); state.setInt(2, 23); state.setString(3, "man"); state.registerOutParameter(4, java.sql.Types.INTEGER); //执行SQL state.execute(); //处理结果 //获取参数 int result = state.getInt(4); if (result==1){ System.out.println("注册成功!"); }else { System.out.println("注册失败!"); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //利用预编译preparedstatement进行更新操作 public void updateprepareDemo(Connection con) { // 准备SQL语句 // String SQL1 = "INSERT INTO student(id,name,age,sex) VALUES(8,'YANGWU',18,'woman')"; // String SQL2 = "DELETE FROM student WHERE id=1"; // 提交数据库的对象 PreparedStatement state = null; Scanner sc = new Scanner(System.in); System.out.println("请输入修改的姓名 :"); String name = sc.nextLine(); System.out.println("请输入年龄 : "); int age = sc.nextInt(); //关闭自动提交 , 事务不会实现数据持久化,即不会写入到数据库里面 try { con.setAutoCommit(false); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String SQL3 = "UPDATE student SET name=? WHERE age=?"; System.out.println(SQL3); //获取状态 try { state = con.prepareStatement(SQL3); //设置参数, SQL语句里面的 ? 按照顺序。 state.setString(1, name); state.setInt(2,age); //executeUpdate 返回一个执行影响行数的int 提交SQL语句,执行SQL int set = state.executeUpdate(); //处理执行结果 if (set > 0) { //结束事务 , 数据上传到数据库, 实现持久化 con.commit(); System.out.println("执行成功: " + set + "行"); }else { //让其回滚。 con.rollback(); } } catch (SQLException e) { e.printStackTrace(); } finally { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } } //更新SQL 操作 @SuppressWarnings("unused") public void updateDemo(Connection con) { // 准备SQL语句 String SQL1 = "INSERT INTO student(id,name,age,sex) VALUES(8,'YANGWU',18,'woman')"; String SQL2 = "DELETE FROM student WHERE id=1"; String SQL3 = "UPDATE student SET name='NIHAO' WHERE id = 1"; // 提交数据库的对象 Statement state = null; try { state = con.createStatement(); //executeUpdate 返回一个执行行数的int int set = state.executeUpdate(SQL1); System.out.println(set); if (set > 0) { System.out.println("执行成功: " + set + "行"); } } catch (SQLException e) { e.printStackTrace(); } finally { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } } //获取连接对象 public static Connection getcon(){ Connection con = null; try { // 获取数据库连接 con = DriverManager.getConnection(url, userName, passWord); } catch (Exception e) { // TODO: handle exception } return con; } // 查询方法 public void selectDemo(Connection con) { // 步骤: // 创建提交对象,,结果集对象 Statement state = null; ResultSet set = null; // 准备SQL语句 String sql = "select * from student"; // 执行SQL语句 // 创建提交数据库的连接 try { // 连接对象 ,执行executeQuery查询命令,并保存到结果集set里面 state = con.createStatement(); set = state.executeQuery(sql); // 处理结果集(对set 结果集进行遍历操作) // next(); 切换到下一条目标数据,如果存在下一条数据则返回true ,否则返回false while (set.next()) { // 每次循环操作一条结果 int id = set.getInt("id"); String name = set.getString("name"); String sex = set.getString("sex"); int age = set.getInt("age"); System.out.println(id + " " + name + " " + sex + " " + age+ ";"); } } catch (Exception e) { e.printStackTrace(); }finally{ try { state.close(); set.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void closeDemo(Connection con) { // 关闭数据库连接 // 处理异常 try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } }