JDBC概述
JDBC(Java Database Connectivity )是java语言操作数据库的API(应用程序接口),它在java.sql.*包下。要在你的IDE中导入相关的数据库jar包,我用的是MySQL数据库和idea编译器,导入的是这个https://pan.baidu.com/s/1u793mqxk_U2FwzsiDa27gAjar包
常用的接口
Connection 连接 代表了java和数据之间的通道,桥梁
Statement 语句 可以用来执行 insert, update, delete , select ...
ResultSet 结果集 代表的是查询的结果
常用的类
DriverManager 工具类,获取连接对象
SQLException 异常对象 是 Exception的子类型,属于检查异常
操作步骤顺序
1、加载驱动 (Driver) jdbc的驱动就是一个连接工厂,生成的产品是连接对象
- com.mysql.jdbc.Driver 是Driver的mysql实现类
- oracle.jdbc.Driver 是Driver的oracle实现类
格式: Class.forName("驱动类名");
例如:Class.forName("com.mysql.jdbc.Driver");// jdbc 3.0 以上版本都可以省略加载驱动这一步
2、获取连接对象
- DriverManager.getConnection(url, 用户名, 密码); // 内部调用了 Driver 对象获取数据库连接,其中url的格式:jdbc:mysql://ip地址:端口号/数据库名?参数
例如:mysql数据库
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");3、创建语句对象
- Statement stmt = conn.createStatement();
4、执行sql
- int rows = stmt.executeUpdate(String sql); // 用来执行 insert , update, delete , DDL , 返回值代表影响行数
- ResultSet rs = stmt.executeQuery(String sql); // 用来执行 select
- boolean moreRows = rs.next() //取得下一条记录, moreRows 是true ,表示有下一条记录, false 表示没有了
5、释放资源( 先打开的资源后关闭 )
上述的第三步和第四步可以用另一个语法创建对象也就是用PreparedStatement (预编译语句)创建对象,它与Statement创建对象不同,它是把sql语句在创建对象是就放入的,也可以用“?”符号来对SQL语句进行占位,并给这个位置赋值,如下:
1.、需要预先提供sql语句
- PreparedStatement psmt = conn.prepareStatement(String sql);
2、可以在sql中用?占位某个值
- 如:String sql ="insert into student(sid,sname,birthday,sex) values(null, ?, ?, ?)" ;
- PreparedStatement psmt = conn.prepareStatement(sql);
3、给?赋值,使用PreparedStatement中一系列以 set开头的方法(位置1开始),有很多例举几个常用,如下
- setString(?的位置, 值)//给类型为String类型的变量赋值,从位置1开始
- setInt(?的位置, 值)//给类型为Int类型的变量赋值,从位置1开始
- setDate(?的位置, 值)//给类型为Date类型的变量赋值,从位置1开始
4、执行sql
- int rows = psmt.executeUpdate();//用来执行 insert , update, delete , DDL , 返回值代表影响行数
- ResultSet rs = psmt.executeQuery();//用来执行 select
- boolean moreRows = rs.next() //取得下一条记录, moreRows 是true ,表示有下一条记录, false 表示没有了
代码演示

1、编写一个方法,以学生的姓名作为条件查询,返回集合
创建一个类,该类中创建一个方法返回数据库连接
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SqlConnection {
//url格式:jdbc:mysql://ip地址:端口号/数据库名?参数
private static final String URL="jdbc:mysql://localhost:3306/school";
//数据库用户名
private static final String USERNAME="root";
//数据库密码
private static final String PASSWORD="root";
//私有构造方法是为了不需要new对象直接调用静态方法,方便
private SqlConnection() {
}
//该方法返回与数据库的连接
public static Connection con() throws SQLException {
//返回与数据库连接
return DriverManager.getConnection(URL,USERNAME,PASSWORD);
}
}
Studnet用来存储表里列的值
import java.sql.Date;
public class Student {
private String sname;//姓名
private String sex;//性别
private Date birthday;//出生日期
private int sid;//学号
//重写toString方法,直接输出Student对象时不会出现地址值,会出现修改过后的值
@Override
public String toString() {
return "Student{" +
"sname='" + sname + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", sid=" + sid +
'}';
}
//构造方法给上面的变量赋值
public Student(int sid, String sname, Date birthday, String sex) {
this.sname = sname;
this.sex = sex;
this.birthday = birthday;
this.sid = sid;
}
//以下都是获得变量值得方法
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
编写一个类,并在之中编写以学生的姓名作为条件查询的方法
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class SelectName {
private SelectName() {
}
//该方法返回类型是集合,参数是你要查找的人名
public static List<Student> method(String name){
//这个try是可以在程序结束时,自动关闭资源,因此这里没有写关闭资源
//括号里是获取连接对象(也就是获取数据库连接对象)
try(Connection connection=SqlConnection.con()){
//用连接好的对象调用prepareStatement,操作SQL语句,这里是以学生的姓名作为条件查询,因此在名字上占个位,这样可以当你想找谁都行,不用固定某人
PreparedStatement psmt = connection.prepareStatement("select * from student where sname like ?");
//给占位处赋值,name是方法的参数
psmt.setString(1,"%"+name+"%");
//执行sql语句,executeQuery表示执行的是select语句,,如果不是查询语句用executeUpdate()
ResultSet resultSet = psmt.executeQuery();
//创建集合对象list用来装Student对象
ArrayList<Student> list = new ArrayList<>();
//遍历数据库表(student表)中的对象,并把对象存入Student对象中,next()为true时指正会指向该处,就可以用get的一系列方法获取
while (resultSet.next()){
//getInt(1)取得学号,getNString(2)取得姓名,getDate(3)取得出生年月,getNString(4)取得性别,它是按列的顺序获取的,而且数据库中的列的位置是从1开始的
Student stu = new Student(resultSet.getInt(1), resultSet.getNString(2), resultSet.getDate(3), resultSet.getNString(4));
//加入list集合中
list.add(stu);
}
//返回list集合
return list;
}catch(SQLException e){
e.printStackTrace();
return null;
}
}
}
上面的get方法里面也可以写数据库中的列名,表示取该列的值,如果改名字了就写新的名字,如:getNString("sid"),sid改名字改为学号,getNString("学号")(select sid 学号 from student),set方法一样可以。
main方法
import java.util.List;
public class SelectNameTest {
public static void main(String[] args) {
//调用SelectName类中查询学生的方法,这里的李表示,查询所有姓李同学的信息,而且因为SelectName的构造方法私有,因此不能new对象,直接用类名调用静态方法就好了
List<Student> list = SelectName.method("李");
//遍历返回的集合中的元素,x表示结合中的Sdtuent对象,然后输出它,后面跟的是lamda表达式
list.forEach(x-> System.out.println(x));
}
}
结果
Student{sname='李四', sex='男', birthday=1981-10-10, sid=1002}
2、编写一个方法,按照学生的编号查询,返回学生对象
该类用于获取数据库连接
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SqlConnection {
//url格式:jdbc:mysql://ip地址:端口号/数据库名?参数
private static final String URL="jdbc:mysql://localhost:3306/school";
//数据库用户名
private static final String USERNAME="root";
//数据库密码
private static final String PASSWORD="root";
private SqlConnection() {
}
//返回数据库连接
public static Connection con() throws SQLException {
return DriverManager.getConnection(URL,USERNAME,PASSWORD);
}
}
该类用于存储表中列的值
import java.sql.Date;
public class Student {
private String sname;//姓名
private String sex;//性别
private Date birthday;//出生年月
private int sid;//学号
@Override
public String toString() {
return "Student{" +
"sname='" + sname + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
", sid=" + sid +
'}';
}
public Student(int sid, String sname, Date birthday, String sex) {
this.sname = sname;
this.sex = sex;
this.birthday = birthday;
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
}
该类用于编写按照学生的编号查询的方法
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SelectSid {
private SelectSid() {
}
//返回类型为Student对象,参数要查询的学号
public static Student method(int sid){
//连接数据库
try(Connection connection=SqlConnection.con()){
//操作SQL语句
PreparedStatement psmt = connection.prepareStatement("select * from student where sid=?");
//给?处赋值,并且是从1开始,有两个?的话就是1、2
psmt.setInt(1,sid);
//执行查询语句,如果不是查询语句用executeUpdate()
ResultSet resultSet = psmt.executeQuery();
//判断是否有下一条语句,并将指针移到该处,并用get语句获得这一行的值
resultSet.next();
//获得的类型根据表中的类型的顺序来
Student stu = new Student(resultSet.getInt(1), resultSet.getNString(2), resultSet.getDate(3), resultSet.getNString(4));
//返回一个Student对象
return stu;
}catch(SQLException e){
e.printStackTrace();
return null;
}
}
}
main方法
public class SelectSidTest {
public static void main(String[] args) {
//查询学号为1003的学生的信息
Student student = SelectSid.method(1003);
System.out.println(student);
}
}
结果
Student{sname='王五', sex='女', birthday=1981-11-10, sid=1003}
3、编写一个方法,查询每个部门的员工人数
编一个获取连接的类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SqlConnection {
private static final String URL="jdbc:mysql://localhost:3306/school";
private static final String USERNAME="root";
private static final String PASSWORD="root";
private SqlConnection() {
}
public static Connection con() throws SQLException {
return DriverManager.getConnection(URL,USERNAME,PASSWORD);
}
}
编写一个类,并在其中编写查询每个部门的员工人数的方法
import java.sql.*;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class SelectNum {
private SelectNum() {
}
public static void method(){
//连接数据库
try(Connection connection=SqlConnection.con()){
//操作sql语句
PreparedStatement psmt = connection.prepareStatement("select deptno,count(*) from emp group by deptno");
//执行查询语句,如果不是查询语句用executeUpdate()
ResultSet rs = psmt.executeQuery();
//用于存储部门编号(主键)和人数(主键所对应的值),
Map<Integer, Integer> map = new TreeMap<>();
while (rs.next()){
//把存储部门编号和部门人数存入map集合中
map.put(rs.getInt("deptno"),rs.getInt("count(*)"));
}
//遍历map集合取出值
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
for (Map.Entry<Integer, Integer> entry : entries) {
System.out.println("部门编号:"+entry.getKey()+" 员工数:"+entry.getValue());
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
main方法
public class SelectNumTest {
public static void main(String[] args) {
SelectNum.method();
}
}
结果
部门编号:10 员工数:3
部门编号:20 员工数:5
部门编号:30 员工数:6
4、获取自增的主键值
import java.sql.*;
public class TestJdbc {
private static final String URL="jdbc:mysql://localhost:3306/school";
private static final String USENAME="root";
private static final String PASSWORD="root";
public static void test(){
String sql="insert into student(sname,birthday,sex) values (?,?,?)";
//获取连接对象
try (Connection conn = DriverManager.getConnection(URL, USENAME, PASSWORD)){
//tatement.RETURN_GENERATED_KEYS 是一个选项,表示要返回自增的主键值
try (PreparedStatement psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS)){
psmt.setString(1,"张丽");
//set日期值时可以是字符串对象,但get日期值时要用getDate
psmt.setString(2,"1998-12-11");
psmt.setString(3,"女");
//执行SQL语句
psmt.executeUpdate();
//返回一个结果集,结果集中存储了刚刚生成的主键值
ResultSet keys = psmt.getGeneratedKeys();
//因为这里只是插入一行,因此返回的也就一个主键,就不需要循环遍历了
keys.next();
//获得主键
int sid = keys.getInt(1);
System.out.println(sid);
}
}catch (SQLException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
test();
}
}
结果
1008

总结
把连接数据库的语句写在一个类中,如果你想改变连接的库或者其他时,你直接修改类中的连接就行了,这样既方便也使代码变简洁了,并且把写的类构造方法私有可以不用创建对象直接调用它的静态方法,会使调用静态方法很方便。