JDBC

JDBC

持久化和持久化技术


  • 持久化技术
    • 概念

把数据保存到可掉电式的存储设备中,持久化的实现过程大多是通过各种关系数据库完成的

  • Java访问数据库的两种方式
    • 直接使用JDBCAPI去访问数据库(mysql/Oracle)
    • 间接地使用JDBCAPI去访问数据库服务器,如HibernateMyBatis
  • JDBC的作用

为访问不同的数据库提供了统一的途径,为开发者屏蔽了一些细节问题。

获取数据库连接


  • 获取连接对象的步骤

记得导入相应的驱动包:mysql-connecttor-java-5.1.26-bin.jar

步骤:
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");

JDBC中常用的API


  • JDBC操作步骤
    • 加载注册驱动
    • 获取连接对象
    • 创建语句对象
    • 执行sql
    • 释放资源(一定要记得关闭资源)

DML操作


对数据库的表进行增加删除修改操作

DQL操作


对数据库的表进行查询操作

DAO的设计思想


  • 概念

DAO(Data Access Object)是一个数据访问接口,数据访问:与数据库打交道。夹在业务逻辑(Service)与数据库资源中间。

  • DAO实现的规范
    • DAO的命名
  com.ghyz.ppd.dao         -- 定义DAO的接口
  com.ghyz.ppd.dao.impl    -- 定义DAO的接口实现类
  com.ghyz.ppd.test        -- 定义测试类
  com.ghyz.ppd.util        -- 定义实体类
  
  // 接口和实现类的规范
  DAO的接口:IXxxDAO,IXxxDao
  DAO的接口实现类XxxDAOImpl,XxxDaoImpl

示例代码


注意,记得关闭Connection,Statement,ReusultSet等类似的资源,下面的代码都省去了关闭资源的步骤

  • IStudentDAO
public interface IStudentDAO {
  /**
  * 保存学生信息
  * @param stu 需要保存的学生对象
  */
  void save(Student stu);
  
  /**
  * 根据id删除对应的学生
  * @param id 需要删除学生的di
  */
  void delete(Long id);
  
  /**
  * 修改学生信息
  * @param stu 封装需要修改的学生信息
  */
  void update(Student stu);
  
  /**
  * 根据id获取对应学生的信息
  * @param Long id
  */
  Student get(Long id);
  
  /**
  * 查询所有的学生信息
  * @return
  */
  List list();
}
  • StudentDAOImpl(DML)
public void save(Student stu) {
  Connection conn = null;
  Statement stmt = null;
  try {
    // 加载驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 获取连接对象
    conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
    // 创建语句对象
    stmt = conn.createStatement();
    // 执行SQL语句
    // 使用StringBuilder进行拼接的速度比较快
    StringBuilder sb = new StringBuilder("INSERT INTO t_student VALUES (NULL,)");
    sb.append("'").append(stu.getName()).append(",");
    sb.append(stu.getAge());
    sb.append(")");
    System.out.prinln(sb);
    st.executeUpdate(sb.toString());
  } catch (Exception e) {
    e.printStackTrace();
  }
}

public void delete(Long id) {
  Connection conn = null;
  Statement stmt = null;
  try {
    // 加载驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 获取连接对象
    conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
    // 执行SQL语句
    String sql = "DELETE FROM t_student WHERE id = " + id;
    // 创建语句对象
    stmt = conn.createStatement();
    stmt.executeUpdate(sql);
  } catch (Exception e) {
    System.out.printStackTrace();
  }
}

public void update(Student stu) {
  Connection conn = null;
  Statement stmt = null;
  try {
    // 加载驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 获取连接对象
    conn = DriverManageer.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
    // 创建语句对象
    stmt = conn.createStatement();
    // 执行SQL语句
    StringBuilder sb = new StringBuilder("UPDATE t_student SET name = ");
    sb.append("'").append(stu.getName()).append("' WHERE id = ").append(stu.getId());
    System.out.println(sb);
    stmt.executeUpdate(sb.toString);
  } catch (Exception e) {
    e.printStackTrace();
  }
}
  • StudentDAOImpl(DQL)
public Student get(Long id) {
  Connection conn = null;
  Statement stmt = null;
  ResultSet rs = null;
  try {
    // 加载注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 获取连接对象
    conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
    // 创建语句对象
    stmt = conn.createStatmenet();
    // 执行SQL语句
    String sql = "SELECT * FROM WHERE id = " + id;
    rs = stmt.executeQuery(sql);
    // 处理结果集
    if (rs.next()) {
      Student stu = new Student();
      stu.setId(id);
      stu.setName(rs.getString("name")
      stu.setAge(rs.getInt("age"));
      return stu;
    }
  } catch(Exception e) {
    e.printStackTrace();
  }
}

public List list() {
  Connection conn = null;
  Statament stmt = null;
  ResultSert rs = null;
  try {
    // 加载驱动
    Class.forName("com.mysql.jdcb.Driver");
    // 获取连接对象
    conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
    // 创建语句对象
    stmt = conn.createStatement();
    // 执行sql语句
    String sql = "SELECT * FROM t_student";
    rs = st.executeQuery()
    while (rs.next()) {
      Student stu = new Student();
      stu.setId(rs.getLong("id"));
      stu.setName(rs.getString("name"));
      stu.setAge(rs.getInt("age"));
      // 将每个学生添加到List集合中
      list.add(stu);
    }
    return list;
  } catch(Exception e) {
    e.printStackTrace();
  }
}

预编译语句对象PreparedStatement


  • 概念

创建一个预编译语句对象,将带有占位符的SQL发送到数据库中进行编译

  • 注意事项

发送参数到数据库中执行sql,千万不要传递参数如果传递了参数,则会调用Statement的方法了

  • 示例代码①
boolean execute();
ResultSet executeQuery();
int executeUpdate();
  • 示例代码②
@Test
public void testStatement() throws Exception {
    Class.forName("com.mysql.jdbc.Driver");
    Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("INSERT INTO t_student(name, age) VALUES('张三', 19)");
}

@Test
public void testPreparedStatement() throws Exception {
  Class.forName("com.mysql.jdbc.Driver");
  Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mytest", "root", "root");
  String sql = "INSERT INTO t_student(name, age) VALUES(?,?)";
  PreparedStatement pstmt = conn.prepareStatement(sql);
  // 为占位符设置参数
  ps.setString(1, "李四");
  ps.setInt(2, 200);
  ps.executeUpdate(); // 不要传递参数
  ps.close();
  conn.close();
}

实现DAO和CRUD的操作


public vod save(Student stu) {
  Connection conn = null;
  PreparedStatement pstmt = null;
  try {
    conn = JdbcUtil.getConnection();
    // 创建语句对象
    String sql = "INSERT INTO t_student VALUES(null, ?, ?)";
    ps = conn.prepareStatement(sql);
    // 为占位符设置
    ps.setString(1, stu.getName());
    ps.setInt(2, stu.getAge());
    ps.executeUpdate();
  } catch(Exception e) {
    e.printStackTrace();
  } finally {
    // 释放资源
    JdbcUtil.close(conn, pstmt, null);
  }
}

public Student get(Long id) {
  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  try {
    conn = JdbcUtil.getConnection();
    // 创建语句对象
    String sql = "SELECT * FROM t_student WHERE id=?";
    pstmt = conn.prepareStatement(sql);
    pstmt.setLong(1, id);
    // 执行SQL语句
    rs = pstmt.excecuteQuery();
    while (rs.next()) {
      Student stu = new Student();
      stu.setId(rs.getLong("id"));
      stu.setName(rs.getString("name"));
      stu.setAge(rs.getAge("age"));
      
      return stu;
    }
  } cathch(Exception e) {
    e.printStackTrace();
  } finally {
    JdbcUtil.close(conn, pstmt, rs);
  }
  return null;
}

Statement与preparedStatement的对比


  • PreparedStatement的优势
    • 语法简单,便于维护
    • 执行的效率更高(MySQL不支持)
    • 安全性更高(防止SQL注入)

数据库事务的概述


  • 事务(Transaction,简写为tx)

指一组逻辑操作单元,使数据从一种状态变换到另一种状态。

为确保数据库中数据的一致性,数据的操作应该是离散的成组的逻辑单元:

当每个逻辑操作单元全部完成时,数据的一致性可以保持。

而当这个单元中的一部分操作失败整个事物应全部视为错误,所有从起点以后的操作应全部回退到开始状态。

  • 事务的操作

给事务定义一个起点,然后对数据做修改操作,这时如果提交(commite),这些修改就永久地保存下来,如果回退(rollback),数据库管理系统将放弃所有的修改而回到开始事务时的状态。

  • 事务的ACID属性:(面试题)

1.原子性(Atomicity)

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。(一损俱损)

2.一致性(Consistency)

事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)

3.隔离性(Isolation)

事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作以及使用的数据对并发的其他事务是隔离的,各个事务之间不能互相干扰。

4.持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

  • DML的操作默认是自动提交的
try {
  // 1.将事务设置为手动提交(设置事务的起点)
  Connection对象.setAutoCommit(false);
  
  // 3.提交事务
  Connection对象.commit();
} catch (Exception e) {
  e.printStackTrace();
  // 2.执行事务回滚操作
  Connection对象.rollback();
}
  • 注意事项

1.在JDBC中,DML的事务是默认提交的,必须设置事务为手动提交

Connecton对象.setAutoCommit(false);

2.手动的提交事务.

connection对象.commit();

3.若出现异常则必须回滚事务:

connection对象.rollback();

MySQL中,InnoDB支持外键,MyISAM不支持外键,不支持事务.

大数据类型操作


  • 示例代码

将图片插入到数据库中

@Test
public void testInsert() throws Exception {
  Connection conn = JdbcUtil.getConnection();
  String sql = "INSERT INTO t_user(headImg) VALUES (?)";
  PreparedStatement pstmt = conn.prepareStatement(sql);
  InputStream in = new FileInputStream("asd.png");
  pstmt.setBlob(1, in);
  pstmt.executeUpdate();
  JdbcUtil.close(conn, pstmt, null);
  in.close();
}

@Test
public void testGet() throws Exception {
  Connection conn = JdbcUtil.getConnection();
  String sql = "SELET headImg FROM t_user WHERE id=?"
  PreparedStatement pstmt = conn.prepareStatement();
  ps.setLong(1, 2L);
  ResultSet rs = ps.executeQuery();
  if (rs.next()) {
    Blob blob = rs.getBlob("headImg");
    // 将二进制数据保存到磁盘中
    InputStream in = blob.getBinaryStream();
    // Java7的新特性,复制文件
    Files.copy(in, Paths.get("head.png"));
    in.close();
  }
  JdbcUtil.close(conn, pstmt, rs);
}

连接池的思想


  • 作用

合理利用连接资源

  • 注意

释放资源Connection对象.close()的时候是是把Connection对象放回连接池,而不是和数据库断开

Druid的使用


  • 使用的步骤
    • 导入jar包(druid-1.0.9.jar)
    • 操作的方式和DBCP大致一样
  • 示例代码
// 获取连接池对象
public static DataSource getDataSource() {
  BasicDataSource ds = new BasicDataSource();
  ds.setDriverClassName("com.mysql.jdbc.Driver");
  ds.setUserName("root");
  ds.setPassword("root");
  ds.setUrl("jdbc:mysql:///mytest");
  retru ds;
}

// 获取连接对象
public static Connection getConnection() throws Exception {
  //使用工厂类创建连接池
  DataSource ds = BasicDataSourceFactory.createDataSource(p);
  // 从连接池中获取对象
  return ds.getConnection();
}

代码重构


  • JdbcUtil
public class JdbcUtil {
  private static Properties p = new Properties();
  static {
    try {
       // 加载资源文件
       ClassLoader loader = Thread.currentThread().getContextClassLoader();
       InputStream ins = loader.getResourceAsStream("db.properties");
       p.load(in);
       // 加载注册驱动
       Class.forName(p.getProperty("driverClassName"));
     )
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
  
  // 获取连接对象
  public static Connection getConnection() throws Exception {
     return DriverManager.getConnection(p.getProperty("url"), p.getProperty("usernmae"), p.getProperty("password"));
  }
}

DML和DQL操作使用PreparedStatement代替Statement


  • 示例代码

DQL查询语句

String sql = "SELECT * FROM t_student";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();

DML修改语句

String sql = "INSERT INTO t_student(id, name) VALUES(null,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "ghyz");
pstmt.executeUpdate();

你可能感兴趣的:(JDBC)