JDBC总结

###JDBC

学习目的:通过java代码访问数据库
- 什么是JDBC: Java Database Connectivity java数据库连接,实际上JDBC就是java语言中一套和数据库交互的api

- 为什么使用JDBC:因为Java程序员工作时需要连接多种数据库(Mysql、oracle,db2等)为了避免每一个数据库都学习一套新的api,Sun公司定义了JDBC接口(方法的声明),各个数据库厂商去写实现类(驱动),这样Java程序员只需要掌握JDBC的调用 即可访问任何数据库。

                                                                 (JDBC接口:一套统一标准的接口

####如何使用JDBC

- 从maven私服中搜索mysql  找到 5.1.6版本的jar坐标 复制到自己的pom文件中。

登陆达内的私服:maven.tedu.cn
登陆阿里私服:maven.aliyun.com
truncate table jdbc01;//删除表并且重建表

具体操作如下:

1. 创建maven工程
2. 下载mysql相关jar包 
- 首页搜索栏输入mysql 搜索
- 找到5.1.6版本 复制坐标 到自己工程的pom.xml文件里

- 实现代码如下:
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3",
"root", "root");
//3.创建sql执行对象
Statement stat = conn.createStatement();
//4. 执行sql
String sql = 
"create table if not exists jdbct1(id int,name varchar(10))";
stat.execute(sql);
System.out.println("执行完成!");
//5. 关闭资源
stat.close();
conn.close();

###JUnit 单元测试
- 可以在一个类中添加多个可执行的方法
- 在无参无返回值的方法上面添加 @Test 右键 run as

package cn.tedu;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import org.junit.Test;

public class Demo02 {
//JUnit单元测试: 在需要运行的方法上面添加@Test注解,
//要求方法必须是无参无返回值。

@Test
public void test01(){
System.out.println("方法一执行");
}
@Test
public void test02(){
System.out.println("方法二执行");
}

@Test
public void insert() throws Exception{
Class.forName("com.mysql.jdbc.Driver");//注册驱动
Connection conn = 
DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3",
"root", "root");//获取连接
Statement stat = conn.createStatement();//执行sql对象
String sql = 
"insert into jdbc01 values(null,'Tom',18)";
stat.executeUpdate(sql);
System.out.println("新增完成");
//关闭资源
stat.close();
conn.close();
}


@Test
public void delete() throws Exception{
Class.forName("com.mysql.jdbc.Driver");//注册驱动
Connection conn = 
DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3",
"root", "root");//获取连接
Statement stat = conn.createStatement();//执行sql对象
String sql = 
"delete from jdbc01 where id=1";
stat.executeUpdate(sql);
System.out.println("删除完成");
//关闭资源
stat.close();
conn.close();
}

@Test
public void update() throws Exception{
Class.forName("com.mysql.jdbc.Driver");//注册驱动
Connection conn = 
DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3",
"root", "root");//获取连接
Statement stat = conn.createStatement();//执行sql对象
String sql = 
"update jdbc01 set age=200 where id=2";
stat.executeUpdate(sql);
System.out.println("修改完成");
//关闭资源
stat.close();
conn.close();
}


@Test
public void findAll() throws Exception{

Class.forName("com.mysql.jdbc.Driver");
Connection conn = 
DriverManager.getConnection(
"jdbc:mysql://localhost:3306/db3", 
"root", "root");
Statement stat = conn.createStatement();
//执行查询
ResultSet rs = 
stat.executeQuery("select * from jdbc01");
while(rs.next()){
//int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println("name:"+name);
}
//关闭资源
rs.close();
stat.close();
conn.close();
 
}

//查询emp表中所用员工的姓名+工资 控制台输出 
//小明每月工资3000元


 

 

 

 

 

package cn.tedu;
/*把死的写活*/
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DBUtils2 {
private static String driver;
private static String url;
private static String username;
private static String password;//全局变量  方便调用
      static {
    //创建属性对象
  Properties prop = new Properties();
  //得到文件的输入流
  InputStream ips = 
  DBUtils2.class.getClassLoader()
  .getResourceAsStream("jdbc.properties");
  //把文件加载到属性对象中
  try {
prop.load(ips);
//读取数据
     driver = prop.getProperty("driver");
     url = prop.getProperty("url");
     username = prop.getProperty("username");
   } catch (IOException e) {
e.printStackTrace();
}
  
      }//static提高执行效率  
      
//1. 获取连接
public static Connection getConn() 
throws Exception{

//注册驱动
Class.forName(driver);
//获取连接对象
Connection conn = 
DriverManager.getConnection(
url,username,password);
return conn;
}
//2. 关闭资源
public static void close(ResultSet rs,
Statement stat,Connection conn){
//关闭resultset
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
//关闭stat
try {
if(stat!=null){
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
//关闭连接
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}

}


####Statement的相关函数
- execute: 可以执行任意sql 但是推荐执行DDL(什么是DDL?这个也比较重要看看前面的笔记)
返回值代表的是 是否有结果集(了解)
- executeUpdate: 推荐执行DML (增删改)
返回值代表的生效行数
- executeQuery:执行DQL
返回值是ResultSet

###测试插入,修改,删除数据 代码参见 Demo02.java
 

###ResultSet
- 此对象中保存着从数据库查询回的数据
- next(): 判断是否有下一条数据有则返回true,并且内部的游标向下移动一格 
- 从对象中获取数据的两种方式:
1.  String name = rs.getString("name");
2.  String name = rs.getString(2); //从1开始

###数据库类型和java类型对比 
mysql数据库               java
int                  getInt
varchar              getString
float/double         getFloat/getDouble
datetime/timestamp   getDate

###解决jdbc乱码问题
在url后面添加    (从?开始)
jdbc:mysql://localhost:3306/db3?useUnicode=true&characterEncoding=UTF-8

 

###数据库连接池 DBCP(http://maven.tedu.cn/ ----> dbcp)
- DataBase Connection Pool: 数据库连接池

- 为什么使用: 如果没有连接池,每一次业务都需要和数据库服务器建立一次连接,业务处理完还要断开连接,如果有上万次业务请求则会有上万次的开关连接,频繁开关连接非常浪费资源,使用数据库连接池可以重复使用连接池中的连接,从而提高网站的响应能力。

(在处理业务时,多次频繁地连接和断开,容易降低效率,而使用数据库连接池中的连接,可以大大提高网站的响应能力)


- 如何使用:
1. 下载相关jar包: 从maven.tedu.cn中搜索dbcp 
2. 关键代码:

//创建数据源对象
BasicDataSource dataSource = 
new BasicDataSource();
//设置数据库连接信息 
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/db3");
dataSource.setUsername("root");
dataSource.setPassword("root");
//设置连接池参数
dataSource.setInitialSize(3);//初始连接数量
dataSource.setMaxActive(5);//最大连接数量
//获取连接池中的连接
Connection conn = dataSource.getConnection();

System.out.println(conn);
package cn.tedu;

/*数据库连接池的使用*/
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import org.apache.commons.dbcp.BasicDataSource;

public class DBUtils3 {
private static String driver;
private static String url;
private static String username;
private static String password;// 全局变量 方便调用
private static BasicDataSource dataSource;
static {
// 创建属性对象
Properties prop = new Properties();
// 得到文件的输入流
InputStream ips = DBUtils3.class.getClassLoader().getResourceAsStream("jdbc.properties");
// 把文件加载到属性对象中
try {
prop.load(ips);
// 读取数据
driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");

// 创建基础数据源
BasicDataSource dataSource = new BasicDataSource();
// 设置数据库连接信息
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
// 设置连接池参数
dataSource.setInitialSize(3);// 初始化数据库连接数量
dataSource.setMaxActive(5);// 最大连接数量
} catch (IOException e) {
e.printStackTrace();
}

}// static提高执行效率

// 1. 获取连接
public static Connection getConn() throws Exception {

Connection conn = dataSource.getConnection();
System.out.println(conn);
return conn;
}

// 2. 关闭资源
public static void close(ResultSet rs, Statement stat, Connection conn) {
// 关闭resultset
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
// 关闭stat
try {
if (stat != null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
// 关闭连接
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}

}

PreparedStatement

  • 预编译的Sql执行对象
  • 好处:
  • 代码可读性更高,不容易出错(因为statement拼接字符串又麻烦又易出错)
  • 带有预编译效果,执行效率比statement略高
  • 可以避免sql注入, 因为预编译的时候已经sql语句的逻辑固定,替换?进去的内容只能以值的形式体现,如果包含逻辑sql内容 则无效

  • sql中有变量就用preparedStatement 没有变量就用statement

  • 使用方式:

  • 关键步骤:
  • //创建预编译sql执行对象
        String sql = 
                "insert into user values(null,?,?)";
        stat = conn.prepareStatement(sql);
        //把?替换成真正的值 
        stat.setString(1, name);
        stat.setInt(2, age);
        //执行sql
        stat.executeUpdate();//返回执行有效的行数

通过登陆案例演示sql注入

create table tlogin (id int primary key autoincrement,username varchar(10),password varchar(10)); insert into t_login values(null,'libai','admin'),(null,'lisi','admin');

select count(*) from t_login where username='sdfsd' and password='' or '1'='1';

注入代码 ' or '1'='1

批量操作 batch

  • 批量操作:可以把多次sql合并成一次执行,避免了频繁和数据库服务器进行交互,从而提高执行效率

  • 代码参见:TestBatch.java

批量插入避免内存溢出

//创建sql执行对象
        String sql = "insert into user values"
                + "(null,?,?)";
        stat = conn.prepareStatement(sql);
        for(int i=0;i<100;i++){
            stat.setString(1, "name"+i);
            stat.setInt(2, i);
            //添加到批量处理
            stat.addBatch();
            if (i%20==0) {
                stat.executeBatch();
                //清空执行过的sql 不然会重复添加
                stat.clearBatch();
            }
        }
        //执行sql
        stat.executeBatch();
        System.out.println("执行完成!");

分页查询 limit 跳过数量和每页条数

在控制台输入页数和每页的数量 得到对应的内容

如: 输入 页数输入3 每页数量输入 5 则得到 第11-15条数据,
       关键点:即分页机制,第一个参数是跳过的页数,第二个参数是每一页多少行记录。

事务(思路)

  1. 设置自动提交的状态 conn.setAutoCommit(true/false);
  2. 提交 conn.commit();
  3. 回滚 conn.rollback();
成年人的世界没有那么多的童话,也没有那么多的逆袭。
原文地址:https://www.cnblogs.com/shijinglu2018/p/9357548.html