MySQL数据库之JDBC入门

xiaoxiao2021-03-01  10

目录

JDBC入门

JDBC各个类详解 

DriverManager:驱动管理对象

Connection:数据库连接对象

Statement:执行sql的对象

PreparedStatement:执行sql的对象

ResultSet:结果集对象,封装查询结果

抽取JDBC工具类

JDBC 登录案例

JDBC控制事务


 

JDBC入门

概念:Java DataBase Connectivity     Java数据库连接

                  * JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

      2. 快速入门:基本操作步骤在代码部分。这只是一段了解JDBC的代码,并不完善,完善代码请看后面。

package JDBC; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; /** * 导包:导入驱动jar包 mysql-connector-java-5.1.37-bin.jar * 1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下 * 2.右键-->Add As Library * <p> * 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar * 2. 注册驱动 * 3. 获取数据库连接对象 Connection * 4. 定义sql * 5. 获取执行sql语句的对象 Statement * 6. 执行sql,接受返回结果 * 7. 处理结果 * 8. 释放资源 */ public class jdbcConnect { public static void main(String[] args) throws Exception { // 1. 加载驱动 Class.forName( "com.mysql.jdbc.Driver" ); // 2. 获取数据连接对象 Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/school", "root", "root" ); // 3. 定义sql String sql = "UPDATE student SET id =101 WHERE id=102"; // 4. 获取执行sql语句的对象 Statement Statement stat = conn.createStatement(); // 5. 执行sql // 返回值是受影响的行数 int i = stat.executeUpdate( sql ); // 6. 处理结果 System.out.println( i ); // 6. 释放资源 stat.close(); conn.close(); } } ==================================================== 1 Process finished with exit code 0

JDBC各个类详解 

DriverManager:驱动管理对象

      功能:         (1)注册驱动:告诉程序该使用哪一个数据库驱动jar                   static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。                   写代码使用:  Class.forName("com.mysql.jdbc.Driver");                   通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块                   static {                         try {                             java.sql.DriverManager.registerDriver(new Driver());                         } catch (SQLException E) {                             throw new RuntimeException("Can't register driver!");                         }                     }

                注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。         (2) 获取数据库连接:                    * 方法:static Connection getConnection(String url, String user, String password)                     * 参数:                          * url:指定连接的路径                                * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称                                * 例子:jdbc:mysql://localhost:3306/db3                                * 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称                     * user:用户名                     * password:密码 

Connection:数据库连接对象

    功能:             1. 获取执行sql 的对象                 * Statement createStatement()                 * PreparedStatement prepareStatement(String sql)               2. 管理事务:                 * 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务                 * 提交事务:commit()                  * 回滚事务:rollback() 

Statement:执行sql的对象

    功能:             1. boolean execute(String sql) :可以执行任意的sql 了解              2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句                 * 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。             3. ResultSet executeQuery(String sql)  :执行DQL(select)语句 ,返回一个结果集 案例:向employee表添加一条数据。

package JDBC; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * student表 添加一条语句 insert */ public class JDBCDemo1 { public static void main(String[] args) { Statement stat = null; Connection conn = null; try { // 1.加载驱动 Class.forName( "com.mysql.jdbc.Driver" ); // 2.定义sql String sql = "insert into employee values(7,'赵虎',19,2)"; // 3.获取Connection对象 conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/school", "root", "root" ); // 4.获取sql对象 stat = conn.createStatement(); // 5.执行sql int count = stat.executeUpdate( sql ); // 6.操作结果 if (count > 0) { System.out.println( "插入数据成功" ); } else { System.out.println( "插入数据失败" ); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { // 7.释放资源 // 防止空指针异常 if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } ================================================= 插入数据成功 Process finished with exit code 0

PreparedStatement:执行sql的对象

  (1) SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题                 1. 输入用户随便,输入密码:a' or 'a' = 'a                 2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 

  (2)解决sql注入问题:使用PreparedStatement对象来解决             预编译的SQL:参数使用?作为占位符             步骤:                 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar                 2. 注册驱动                 3. 获取数据库连接对象 Connection                 4. 定义sql                     * 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;                 5. 获取执行sql语句的对象 PreparedStatement  Connection.prepareStatement(String sql)                  6. 给?赋值:                     * 方法: setXxx(参数1,参数2)                         * 参数1:?的位置编号 从1 开始                         * 参数2:?的值                 7. 执行sql,接受返回结果,不需要传递sql语句                 8. 处理结果                 9. 释放资源

   (3) 注意:后期都会使用PreparedStatement来完成增删改查的所有操作                 1. 可以防止SQL注入                 2. 效率更高

ResultSet:结果集对象,封装查询结果

      功能: 

              * boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true              * getXxx(参数):获取数据                         * Xxx:代表数据类型   如: int getInt() ,    String getString()                         * 参数:                                  1. int:代表列的编号,从1开始   如: getString(1)                                  2. String:代表列名称。 如: getDouble("id")   表示获取employee表里id列的值

             * 使用步骤:                                  1. 游标向下移动一行                                  2. 判断是否有数据                                 3. 获取数据 案例:定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。(省略了定义employee实体类的过程)

package JDBC; import domain.employee; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。 * 1. 定义Emp类 * 2. 定义方法 public List<Emp> findAll(){} * 3. 实现方法 select * from emp; */ public class JDBCDemo4 { public static void main(String[] args) { //调用findAll方法 List<employee> list = new JDBCDemo4().findAll(); for (employee employee : list) { System.out.println( employee ); } } public List<employee> findAll() { Connection conn = null; Statement stat = null; ResultSet rs = null; List<employee> list = null; try { // 1.加载驱动 Class.forName( "com.mysql.jdbc.Driver" ); // 2.定义sql String sql = "select * from employee"; // 3.获取Connection对象 conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/school", "root", "root" ); // 4.获取执行sql的对象 stat = conn.createStatement(); // 5.执行sql rs = stat.executeQuery( sql ); // 6.处理结果,遍历结果集,封装对象,装载到集合中 list = new ArrayList<employee>(); employee emp = null; while (rs.next()) { //创建employee对象 emp = new employee(); emp.setId( rs.getInt( "id" ) ); emp.setName( rs.getString( "name" ) ); emp.setAge( rs.getInt( "age" ) ); emp.setDep_id( rs.getInt( "dep_id" ) ); //添加到集合中 list.add( emp ); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { // 释放资源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } } ============================================================ employee{id=1, name='张三', age=20, dep_id=3} employee{id=2, name='李四', age=21, dep_id=3} employee{id=3, name='王五', age=20, dep_id=3} employee{id=4, name='老王', age=20, dep_id=2} employee{id=5, name='大王', age=22, dep_id=2} employee{id=6, name='小王', age=18, dep_id=2} Process finished with exit code 0

抽取JDBC工具类

目的:简化书写

分析:          1. 注册驱动抽取          2. 抽取一个方法获取连接对象            **   不传递参数,必须保证工具类的通用性能,需要创建一个配置文件,配置文件里存放数据库地址,用户名,密码,驱动          3. 抽取一个方法释放资源

 配置文件:

url=jdbc:mysql://localhost:3306/school user=root password=root driver=com.mysql.jdbc.Driver

JDBC工具类: 

package tool; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC工具类 */ public class JDBCUtils { /** * 静态变量才能被静态代码块和静态方法访问 */ private static String url; private static String user; private static String password; private static String driver; /** *文件的读取,只需要读取一次就可以拿到这些值。可以使用静态代码块,随着类的加载而执行一次 * 静态代码块中的异常只能处理,不能抛出 */ static { //读取资源文件,获取值 try { // 1.创建properties集合类 Properties pro = new Properties(); //获取src路径下的文件的方式--->ClassLoader 类加载器 ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL res = classLoader.getResource( "jdbc.properties" ); String path = res.getPath(); // 2.加载文件 // pro.load( new FileReader( "E:\\IdeaProject\\ShuangYuan\\day15\\jdbc.properties" ) ); pro.load( new FileReader( path ) ); // 3.获取数据,赋值 url = pro.getProperty( "url" ); user = pro.getProperty( "user" ); password = pro.getProperty( "password" ); driver=pro.getProperty( "driver" ); Class.forName( driver ); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取连接 * * @return Connection连接对象 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection( url,user,password ); } /** * 释放资源 * * @param stat * @param conn */ public static void close(ResultSet rs, Statement stat, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }

JDBC 登录案例

需求:           1.  通过键盘录入用户名和密码           2.  判断用户登录是否成功,反馈信息打印到控制台

创建User表:

CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32), PASSWORD VARCHAR(32) ); INSERT INTO USER VALUES(NULL,'zhangsan','123'); INSERT INTO USER VALUES(NULL,'lisi','456');

 登录代码:

package JDBC; import tool.JDBCUtils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; /** * 需求: * 1. 通过键盘录入用户名和密码 * 2. 判断用户是否登录成功 */ public class JDBCDemo5 { public static void main(String[] args) { Scanner sc=new Scanner( System.in ); System.out.println("请输入用户名:"); String username = sc.nextLine(); System.out.println("请输入密码:"); String password = sc.nextLine(); boolean login = new JDBCDemo5().login( username, password ); if(login){ System.out.println("登录成功"); }else{ System.out.println("登录失败"); } } /** * 登录方法 * @param username * @param password * @return */ public boolean login(String username, String password) { // 若用户名和密码为空,返回false if (username == null || password == null) { return false; } Connection conn = null; Statement stat = null; ResultSet rs = null; try { // 1.获取连接 conn = JDBCUtils.getConnection(); // 2.定义sql String sql = "select * from user where username = '" + username + "' and password = '" + password + "' "; // 3.获取执行sql的对象 stat = conn.createStatement(); // 4.执行SQL语句 rs = stat.executeQuery( sql ); return rs.next(); } catch (SQLException e) { e.printStackTrace(); } finally { // 5.释放资源 JDBCUtils.close( rs, stat, conn ); } return false; } }

测试结果: 

请输入用户名: zhangsan 请输入密码: 123 登录成功 Process finished with exit code 0 ========================================== 请输入用户名: zhangsan 请输入密码: 32424324 登录失败 Process finished with exit code 0 ========================================== 请输入用户名: lisi 请输入密码: 456 登录成功 Process finished with exit code 0

注意:上述代码是有问题的,如下用户名和密码在数据库中都不存在,但是却登录成功了,这是为什么呢?其实我们看下它的sql语句就可以看出来,最后的字符串拼接,or 'a' = 'a' ,or后面是一个恒等式,所以自然就成立,这就是SQL注入问题--(SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令)。 sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 

请输入用户名: dasd sa 请输入密码: a' or 'a' = 'a 登录成功 Process finished with exit code 0

解决sql注入问题的方案:使用PreparedStatement对象来解决

预编译的SQL:参数使用 ? 作为占位符

// 1.获取连接 conn = JDBCUtils.getConnection(); // 2.定义sql String sql = "SELECT * from user WHERE username=? and password=?"; // 3.获取执行sql的对象 ps = conn.prepareStatement( sql ); // 4.给?赋值 ps.setString(1,username); ps.setString( 2,password ); // 5.执行查询,不需要传递sql rs = ps.executeQuery();

JDBC控制事务

(1)事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。 (2 )  操作:               1. 开启事务               2. 提交事务               3. 回滚事务 (3)使用Connection对象来管理事务               * 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务                       * 在执行sql之前开启事务               * 提交事务:commit()                        * 当所有sql都执行完提交事务               * 回滚事务:rollback()                       * 在catch中回滚事务 

public class JDBCDemo10 { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt1 = null; PreparedStatement pstmt2 = null; try { //1.获取连接 conn = JDBCUtils.getConnection(); //开启事务 conn.setAutoCommit(false); //2.定义sql //2.1 张三 - 500 String sql1 = "update account set balance = balance - ? where id = ?"; //2.2 李四 + 500 String sql2 = "update account set balance = balance + ? where id = ?"; //3.获取执行sql对象 pstmt1 = conn.prepareStatement(sql1); pstmt2 = conn.prepareStatement(sql2); //4. 设置参数 pstmt1.setDouble(1,500); pstmt1.setInt(2,1); pstmt2.setDouble(1,500); pstmt2.setInt(2,2); //5.执行sql pstmt1.executeUpdate(); // 手动制造异常 int i = 3/0; pstmt2.executeUpdate(); //提交事务 conn.commit(); } catch (Exception e) { //事务回滚 try { if(conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils.close(pstmt1,conn); JDBCUtils.close(pstmt2,null); }

 

转载请注明原文地址: https://www.6miu.com/read-4150161.html

最新回复(0)