JDBC [Java DataBase Connectivity] JAVA数据库连接
JDBC是SUN提供的一套API接口,使用JAVA连接数据库的一套标准接口。
各个数据库提供上都提供了一套JDBC的实现类用于连接自家的DBMS。而提供的这一套
实现类也称为连接该DBMS的驱动(Driver)
1:要加载需要操作的DBMS厂商提供的驱动(MAVEN直接加载依赖)
2:基于标准的JDBC操作流程操作该数据库
/*
JDBC连接DBMS的标准流程
1:加载驱动:Class.forName("不同数据库厂商提供的Driver类")
2:与数据库建立连接:DriverManager.getConnection()
3:通过Connection对象创建用于执行SQL语句的Statement对象
4:通过Statement执行SQ语句
5:如果执行的是DQL,则可以遍历查询结果集
*/
//1 JDBC中Driver接口的实现类不同数据库厂商提供的的包名与类名不相同
Class.forName("com.mysql.cj.jdbc.Driver");//mysql固定就是这个
//2
/*
DriverManager.getConnection()方法需要传入三个参数
1:连接数据库的路径(不同的数据库路径格式不完全相同)
2:连接数据库的用户名
3:连接数据库的密码
该方法返回值为一个Connection的实例(Connection是一个接口,是
JDBC中的一个核心接口,用于表示一个与数据库的连接。不同的数据库
厂商在驱动包里提供了对应的实现类)
*/
//URL格式-> jdbc:不同数据库有自己格式的部分/数据库名?参数
Connection connection = DriverManager.getConnection(
// 数据库名,相当于USE tedu
// ||||
// VVVV
"jdbc:mysql://localhost:3306/tedu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true",
"root",
"root");
System.out.println("数据库连接成功!");
/*
通过Connection获取用于执行SQL语句的执行对象Statement
Statement对象的作用就是向数据库执行指定的SQL语句。
*/
Statement state = connection.createStatement();
/*
创建一张表userinfo
字段:id,username,password,nickname,age
*/
String sql = "CREATE TABLE userinfo(" +
" id INT AUTO_INCREMENT PRIMARY KEY," +
" username VARCHAR(30)," +
" password VARCHAR(30)," +
" nickname VARCHAR(30)," +
" age INT(3)" +
")";
/*
boolean execute(String sql)
该方法可以执行任意分类的SQL语句。但是DML和DQL都有专门的方法
用于执行,因此该方法一般用于指定DDL语句(CREATE,ALTER,DROP)
该方法返回值为true表达该SQL执行后有查询结果集。
*/
state.execute(sql);
System.out.println("SQL执行完毕");
执行DML语句(INSERT,UPDATE,DELETE)
Class.forName("com.mysql.cj.jdbc.Driver");
try(
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/tedu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true",
"root",
"root");
) {
Statement state = connection.createStatement();
String sql = "INSERT INTO student1(name,age,class_id) " +
" VALUES('张三',12,1)";
/*
int executeUpdate(String sql)
专门用来执行DML语句的方法,返回值为执行该SQL后影响了表中多少条记录
*/
int count = state.executeUpdate(sql);//INSERT插入1条数据
if(count>0){//执行后至少影响了表中1条数据
System.out.println("影响了表中"+count+"条数据");
}
System.out.println("执行完毕");
}catch(SQLException e){
e.printStackTrace();
}
执行DQL语句(SELECT)
/*
查看所有老师的id,名字,年龄,工资,奖金,性别
SELECT id,name,age,salary,comm,gender
FROM teacher
*/
try(
Connection connection = DBUtil.getConnection();
){
Statement state = connection.createStatement();
/*
SELECT子句某个字段如果是一个计算表达式,或者函数.那么应当为该字段
指定别名.
*/
String sql = "SELECT id,name,age,salary*12 sal,comm,gender " +
"FROM teacher ";
System.out.println(sql);
/*
Statement中
ResultSet executeQuery(String sql)
专门用户来执行DQL语句的方法。返回的ResultSet表示执行该DQL后
产生的查询结果集。通过遍历该结果集得到查询内容
*/
ResultSet rs = state.executeQuery(sql);
/*
ResultSet遍历结果集中重要的方法:
boolean next()
让结果集指针向下移动一条数据,如果结果集存在下一条数据则返回
true否则返回false。
注:指针默认在结果集第一条记录之前。
获取指针当前指向的结果集中该条记录的字段值对应的方法:
String getString(int c)
获取字符串类型字段的值,c表示结果集中该条记录的第几个字段
1表示第一个字段,2表示第二个字段以此类推
String getString(String cname)
获取字符串类型字段的值,cname表示结果集中该条记录指定名字的字段值
int getInt(int c)
int getInt(String cname)
获取int型字段值
同样还有获取浮点型,日期型等方法...
*/
while(rs.next()){
//获取id
// int id = rs.getInt(1);
// String name = rs.getString(2);
// int age = rs.getInt(3);
// int salary = rs.getInt(4);
// int comm = rs.getInt(5);
// String gender = rs.getString(6);
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
//如果DQL中SELECT的字段有别名,这里获取结果集对应字段要用别名
int salary = rs.getInt("sal");
int comm = rs.getInt("comm");
String gender = rs.getString("gender");
System.out.println(id+","+name+","+age+","+salary+","+comm+","+gender);
}
}catch(SQLException e){
e.printStackTrace();
}
关联查询
try (
Connection connection = DBUtil.getConnection();
){
Statement statement = connection.createStatement();
//查看1年级1班的学生名字,年龄,性别,班级名称,班主任名字
String sql = "SELECT s.name sname,s.age sage,s.gender sgender,c.name cname,t.name tname " +
"FROM student s " +
"JOIN class c ON s.class_id=c.id " +
"JOIN teacher t ON c.teacher_id=t.id " +
"WHERE c.name='1年级1班'";
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
String sname = rs.getString("sname");
int sage = rs.getInt("sage");
String sgender = rs.getString("sgender");
String cname = rs.getString("cname");
String tname = rs.getString("tname");
System.out.println(sname+","+sage+","+sgender+","+cname+","+tname);
}
} catch (SQLException e) {
e.printStackTrace();
}
执行预编译SQL语句
优点:
1:避免了繁琐的拼接SQL语文
2:避免了被SQL注入的问题
3:大批量执行相同语义的SQL(语义相同,值不同)时性能好
实际开发中我们的CRUD都建议使用预编译SQL来执行
try (
Connection conn = DBUtil.getConnection();
){
//向userinfo表中插入数据
String sql = "INSERT INTO userinfo " +
"(username,password,nickname,age) " +
"VALUES " +
"(?,?,?,?)";//预编译SQL中可以先用"?"代替值
/*
此时Connection会现将该SQL发送给数据库,使其生成该SQL的
执行计划,表明该SQL的语义.
数据库理解了,要向userinfo表插入数据,并且对4个字段插入内容
只不过该SQL不能真正执行,因为还没有数据.
*/
PreparedStatement ps = conn.prepareStatement(sql);
//使用PreparedStatement为四个预留的"?"设置应有的值
ps.setString(1,"张三");//第1个?的值为字符串类型的"王克晶"
ps.setString(2,"123456");
ps.setString(3,"三三");
ps.setInt(4,18);//第4个?的值为int类型的数字18
//此时执行时仅将4个?对应的值传递给数据库
int count = ps.executeUpdate();
if(count>0){
System.out.println("插入成功");
}
} catch (SQLException e) {
e.printStackTrace();
}
SELECT语句
try (
Connection conn = DBUtil.getConnection();
){
String sql = "SELECT id,username,password,nickname,age " +
"FROM userinfo " +
"WHERE username=? AND password=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,"王克晶");
// ps.setString(2,"666666");
ps.setString(2,"' OR '1'='1");
ResultSet rs = ps.executeQuery();
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
} catch (SQLException e) {
e.printStackTrace();
}