什么是JDBC?
Java语言访问数据库的一种规范,是一套API。
JDBC (Java Database Connectivity) API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库。比如建立数据库连接、执行SQL语句进行数据的存取操作。
JDBC库中所包含的API任务通常与数据库使用:
•连接到数据库
•创建SQL或MySQL语句
•在数据库中执行SQL或MySQL查询
•查看和修改记录
使用JDBC的主要API:
- DriverManager 驱动程序,为数据库连接提供支持。
- Connection 连接某一指定的数据库
- Statement 执行sql语句,获取查询方法,有两个子接口(CallableStatement, PreparedStatement)
- ResultSet 对结果集进行处理
execute、executeQuery和executeUpdate之间的区别?
方法executeQuery:
用于产生单个结果集(ResultSet)的语句。 这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。但也只能执行查询语句,执行后返回代表查询结果的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语句了。
导入jdbc jar包
封装连接数据库的类
public class DBUtil {
private static final String URL = "jdbc:mysql://localhost:3306/mss?useSSL=true";
private static final String NAME = "root";
private static final String PASSWORD = "911587154";
private static Connection conn = null;
// 静态代码块(将加载驱动、连接数据库放入静态块中)
static {
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(URL, "root", "911587154");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() {
return conn;
}
}
增删改查(CURE)操作
package test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DBDataAction {
/**
* 输入数据表的完整数据进行添加
* @param name
* @param sex
* @param age
* @param date
*/
public void addData(String name, int sex, int age, Date date) {
Connection conn = DBUtil.getConnection();
String sql = "insert into user(name,sex,age,birthday) values(?,?,?,?)";
PreparedStatement psmt = null;
// 预编译sql语句
try {
psmt = conn.prepareStatement(sql);
// 先对应SQL语句,给SQL语句传递参数
psmt.setString(1, name);
psmt.setInt(2, sex);
psmt.setInt(3, age);
psmt.setDate(4, new java.sql.Date(date.getTime()));
psmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (psmt != null) {
try {
psmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 根据列名和参数删除指定的数据库
* @param column
* @param parm
*/
public void deleteData(String column, String parm) {
Connection conn = DBUtil.getConnection();
String sql = "delete from user where " + column + "=?";
PreparedStatement psmt = null;
// 预编译sql语句
try {
psmt = conn.prepareStatement(sql);
// 先对应SQL语句,给SQL语句传递参数
psmt.setString(1, parm);
psmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (psmt != null) {
try {
psmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 修改一条记录全部的数据
* @param name
* @param sex
* @param date
* @param age
* @param id
*/
public void updateData(String name, int sex, Date date, int age, int id) {
Connection conn = DBUtil.getConnection();
String sql = "update user set name=?,sex=?,birthday=?,age=? where id=?";
PreparedStatement psmt = null;
// 预编译sql语句
try {
psmt = conn.prepareStatement(sql);
// 先对应SQL语句,给SQL语句传递参数
psmt.setString(1, name);
psmt.setInt(2, sex);
psmt.setDate(3, new java.sql.Date(date.getTime()));
psmt.setInt(4, age);
psmt.setInt(5, id);
psmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (psmt != null) {
try {
psmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 使用频率最高的操作,使用了特殊方法增加了查询的灵活性
* @param params
*/
public void queryData(List<Map<String, Object>> params) {
Connection conn = DBUtil.getConnection();
StringBuffer sb = new StringBuffer();
sb.append("select * from user where 1=1 ");// 注意where 1=1 的小技巧
if (params != null && params.size() > 0) {// 先判断集合是否为空
// 遍历集合
for (int i = 0; i < params.size(); i++) {
Map<String, Object> map = params.get(i);
sb.append("and " + map.get("name") + " " + map.get("rela") + " " + map.get("value") + " ");// 查询什么?关系是什么?以及值是什么,我们都可以通过参数传进来。
}
}
//System.out.println(sb.toString());
PreparedStatement psmt = null;
ResultSet rs = null;
// 预编译sql语句
try {
psmt = conn.prepareStatement(sb.toString());
rs = psmt.executeQuery();
while (rs.next()) {
rs.getInt("id");
rs.getString("name");
rs.getInt("age");
rs.getInt("sex");
rs.getDate("birthday");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (psmt != null) {
psmt.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//删
// new DBDataAction().deleteData("id","1");
//增
//new DBDataAction().addData("mss", 1, 13, new Date());
//改
//new DBDataAction().updateData("dsf", 0, new Date(), 34, 1);
//查
List<Map<String, Object>> parms=new ArrayList<>();
Map<String, Object> parm=new HashMap<>();
parm.put("name", "name");
parm.put("rela", "=");
parm.put("value", "'shanshui'");//注意加上单引号,因为这个变量是字符串的形式
parms.add(parm);
parm=new HashMap<>();
parm.put("name", "age");
parm.put("rela", "=");
parm.put("value", "15");//注意加上单引号,因为这个变量是字符串的形式
parms.add(parm);
new DBDataAction().queryData(parms);
}
}
prepareStatement这个方法会将SQL语句加载到驱动程序conn集成程序中,但是并不直接执行而是当它调用execute()方法的时候才真正执行。
上面SQL中的参数用?表示,相当于占位符,然后在对参数进行赋值。
当真正执行时,这些参数会加载在SQL语句中,把SQL语句拼接完整才去执行。这样就会减少对数据库的操作
这个查询的亮点在于:使用get(List < Map< String,Object>> params) 和 where 1=1;
jdbc传参数过多的时候:用List< Map< String,Object>> params双泛型作为参数.
我们查询的每一个条件都是一个键值对。键值对的数据结构就是Map。
然后是因为查询的条件可能是多个,数量不确定,所以用List 比较好,所以就会是List< Map < key,value>>这样的数据结构了。
上面使用where 1=1的原因主要是下面的语句直接就跟着一个and。SQL语句后面需要跟着where,但不确定where后面是否有语句,就要加上1=1,保证语法不会出错。
一般用于构造动态SQL语句,”SELECT … FROM … WHERE 1=1 “+动态构造条件子句。
在使用JDBC时要及时释放资源,一般在静态代码块中写连接数据库(Connection )的操作,然后Connection 就一直放在内存中,不要关闭,当使用Statement 执行sql语句和ResultSet 对结果集进行处理时要释放,一般从小到大先close ResultSet 在close Statement 。、
事务管理
关于事务是什么我就不说了,网上有很多介绍,简单的说就是定义一系列的数据库操作,其中有一个失败全部的操作都取消。这里我简单讲一下他如何使用:
public class DBDataAction {
/**
* 输入数据表的完整数据进行添加
* @param name
* @param sex
* @param age
* @param date
* @throws SQLException
*/
public void addData(Connection conn,String name, int sex, int age, Date date) throws SQLException {
String sql = "insert into user(name,sex,age,birthday) values(?,?,?,?)";
PreparedStatement psmt = null;
// 预编译sql语句
psmt = conn.prepareStatement(sql);
// 先对应SQL语句,给SQL语句传递参数
psmt.setString(1, name);
psmt.setInt(2, sex);
psmt.setInt(3, age);
psmt.setDate(4, new java.sql.Date(date.getTime()));
psmt.executeUpdate();
}
/**
* 修改一条记录全部的数据
* @param name
* @param sex
* @param date
* @param age
* @param id
* @throws SQLException
*/
public void updateData(Connection conn,String name, int sex, Date date, int age, int id) throws SQLException {
String sql = "update user set name=?,sex=?,birthday=?,age=? where id=?";
PreparedStatement psmt = null;
// 预编译sql语句
psmt = conn.prepareStatement(sql);
// 先对应SQL语句,给SQL语句传递参数
psmt.setString(1, name);
psmt.setInt(2, sex);
psmt.setDate(3, new java.sql.Date(date.getTime()));
psmt.setInt(4, age);
psmt.setInt(5, id);
psmt.executeUpdate();
}
public static void main(String[] args) {
Connection conn=ConnectionFactory.getConnection();
try {
//数据库不自动提交
conn.setAutoCommit(false);
new DBDataAction().addData(conn,"mss", 1, 13, new Date());
new DBDataAction().updateData(conn,"dsf", 0, new Date(), 34, 1);
//提交事务
conn.commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
try {
//回滚事务
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}