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语句的执行对象StatementStatement对象的作用就是向数据库执行指定的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,genderFROM 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();}