Java DataBase Connectivity
连接作用,桥梁的作用,连接一头是Java,一头是数据库
JDBC可以连接很多数据库,但是需要依赖每个数据库的驱动包,比如:
mysqlXXX.jar,oracleXXX.jar等。
JDBC它是一系列的API,是JDK中的,它自身不能连接数据库,它只是API,要连接数据库需要各数据库厂商的驱动包。这是狭义上的概念。
我们通常说的JDBC是一种连接数据库并操作数据库的现象。
JDBC是一个底层的连接技术,是一个过渡,实际开发中不用,用框架。
在学习之初使用,主要是了解连接的底层技术。它的程序性能是非常好的,但是开发效率低,所以后期使用框架较多。
1.需要数据库的驱动包
2.编码
1)加载驱动类
2)获取连接
3)操作数据库
4)关闭连接
package c59; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBC1 { public static void main(String[] args) { Connection conn = null; try { // 1.加载驱动类,数据库不同,类名不同 Class.forName("com.mysql.jdbc.Driver"); // 2.获取数据库连接,需要提供连接字符串(主机名/IP,端口号,数据库名) // 需要提供连接时的用户名和密码(数据库用户名和密码) // 如果Java操作数据库时出现了中文乱码,在连接字符串中加参数 String url = "jdbc:mysql://localhost:3306/uolab?useUnicode=true&characterEncoding=utf8"; String username = "root"; String pwd = "ychs2021"; conn = DriverManager.getConnection(url, username, pwd); System.out.println("连接成功"); // 数据库关键字大写,表名字段名小写,SQL语句如果是多行, // 在下一行的开头写上空格(因为关键字左右需要空格) String sql = "INSERT INTO college(name,code,updatetime)" + " VALUES('软件工程',3,sysdate())"; // Statement接口,PreparedStatement接口操作数据库,它们向数据库发送命令 Statement statement = conn.createStatement(); // 执行sql,向数据库发送命令 int result = statement.executeUpdate(sql); // 打印sql执行的结果(影响的行数) System.out.println("result=" + result); } catch (SQLException | ClassNotFoundException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
package c59; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBC2 { public static void main(String[] args) { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/uolab" + "?useUnicode=true&characterEncoding=utf8"; String username = "root"; String pwd = "ychs2021"; conn = DriverManager.getConnection(url, username, pwd); //java.io.IOException java.lang.InterruptedException java.sql.SQLException String sql = "UPDATE college SET name='软工' WHERE id=3"; // PreparedStatement是Statement的子接口,它具有预编译,预处理的功能 // 所以效率要比Statement高,而且它可以识别sql语句中的参数和占位符(可以传参) // 如果sql语句中的参数较多,需要拼接字符串时,用PreparedStatement非常方便 PreparedStatement ps = conn.prepareStatement(sql); // 执行一切sql //ps.execute(); // 执行增删改的sql int result = ps.executeUpdate(); System.out.println("result=" + result); // 执行查询的sql //ps.executeQuery(); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
ResultSet结果集,从数据库中获取的数据在这个对象里。
从ResultSet中获取数据。
package c59; import java.sql.*; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBCQuery { public static void main(String[] args) { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/uolab" + "?useUnicode=true&characterEncoding=utf8"; String username = "root"; String pwd = "ychs2021"; conn = DriverManager.getConnection(url, username, pwd); String sql = "SELECT * FROM USER WHERE username='admin'" + " AND password='admin'"; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); // rs获取数据,rs就是数据库游标 // next相当于游标的指针向前移动,并且返回boolean值,是否有记录 while (rs.next()) { // 获取数据有两种方法,一个是按照列的索引来获取,一个是按照列名来获取 // 索引从1开始 int id = rs.getInt(1); // college不一定是列名,也可能是列的别名 String college = rs.getString("college"); java.util.Date date = rs.getDate("updatetime"); System.out.println("id=" + id); System.out.println("college=" + college); System.out.println("updatetime=" + date); // 到此一条记录读取完成,下一个循环是下一条记录 } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
package c59; import java.sql.*; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBCQuery2 { public static void main(String[] args) { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql:///uolab" + "?useUnicode=true&characterEncoding=utf8"; String username = "root"; String pwd = "ychs2021"; conn = DriverManager.getConnection(url, username, pwd); // 假设u的变量的值是来自于网页 String u = "admin"; // Statement在拼接sql语句时会有sql注入的漏洞 String p = "123' OR '1=1";// password = '123' OR '1=1' // 字符串拼接时注意当值是字符时,两边要加"'"单引号 /*String sql = "SELECT * FROM USER WHERE username='" + u + "'" + " AND password='" + p + "'";*/ // sql漏洞 /*String sql = "SELECT * FROM USER WHERE username='" + u + "'" + " AND password='" + p + "' OR 1=1";*/ String sql = "SELECT * FROM USER WHERE username='" + u + "'" + " AND password='" + p + "'"; System.out.println("sql=" + sql); // Statement创建时不用sql,PreparedStatement创建时需要sql语句,因为它要 // 对sql进行预编译,预处理 Statement stmt = conn.createStatement(); // Statement执行的时候需要指定sql,PreparedStatement因为之前已经处理过, // 执行时不需要指定sql ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { Object id = rs.getObject("id"); Object college = rs.getObject("college"); Object updatetime = rs.getObject("updatetime"); System.out.println("id=" + id); System.out.println("college=" + college); System.out.println("updatetime=" + updatetime); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
package c59; import java.sql.*; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBCQuery3 { public static void main(String[] args) { // 利用PreparedStatement来堵住SQL漏洞 Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql:///uolab?useUnicode=true&characterEncoding=utf8"; conn = DriverManager.getConnection(url, "root", "ychs2021"); String username = "admin"; String pwd = "123' or '1=1'"; // 利用参数的占位符带替了SQL语句的拼接,没有拼接就没有漏洞 String sql = "SELECT * FROM USER WHERE username = ? AND password = ?"; PreparedStatement ps = conn.prepareStatement(sql); // 因为SQL语句中有参数的占位符,在执行前,需要对这些占位符传入具体的数值 // 因为传入的字符串不管是什么,ps都会在其两边加上"'",所以堵住了漏洞 ps.setString(1, username); ps.setString(2, pwd); //ps.setObject(1, username); //ps.setObject(2, pwd); ResultSet rs = ps.executeQuery(); while (rs.next()) { Object id = rs.getObject("id"); System.out.println("id=" + id); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
对于有多条SQL需要批量执行时,用批处理,效率会高。
产先把SQLaddBacth加到批中,executeBatch执行批量。
返回的结果是一个数组,但是不能像单条SQL执行那样得到准确的结果。
package c59; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Arrays; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBCBatch { public static void main(String[] args) { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql:///uolab"; conn = DriverManager.getConnection(url, "root", "ychs2021"); String sql = "INSERT INTO major(id,name,code,college,updatetime)" + " VALUES(?,?,?,?,sysdate())"; PreparedStatement ps = conn.prepareStatement(sql); // 因为是批量,用for循环 for (int i = 1; i < 10; i++) { ps.setObject(1, i); ps.setObject(2, "name"+i); ps.setObject(3, i); ps.setObject(4, 1); // 加到批处理中 ps.addBatch(); } // 批量处理 int[] result = ps.executeBatch(); System.out.println(Arrays.toString(result)); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
-- 根据id删除专业 create procedure p_delete_major(v_id int) begin delete from major where id=v_id; end -- 调用存储过程 call p_delete_major(9);
package c59; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * copyright(c)2021 YCKJ.ALL rights Reserved * <p> * 描述: * * @author ychs * @version 1.0 * @date 2021/5/9 */ public class JDBCCall { public static void main(String[] args) { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql:///uolab"; conn = DriverManager.getConnection(url,"root","ychs2021"); // 调用存储过程 String sql = "{CALL p_delete_major(?)}"; CallableStatement cs = conn.prepareCall(sql); //cs.setInt(1, 8); //cs.setInt("v_id", 8); cs.setObject(1, 8); int result = cs.executeUpdate(); System.out.println("result=" + result); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }