资讯详情

尚硅谷JDBC笔记

JDBC核心技术

讲师:宋红康

微博:尚硅谷-宋红康


第1章:JDBC概述

1.1 数据的持久性

  • 持久化(persistence):。在大多数情况下,其是企业级应用,上加固化

  • 持久性的主要应用是将内存中的数据存储在关系数据库中,当然也可以存储在磁盘文件中XML在数据文件中。

    [外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-9l8Emtij-1657010009237)(尚硅谷_宋红康_JDBC.assets/1566741430592.png)]

1.2 Java数据存储技术

  • 在Java数据库存取技术可分为以下几类:

    • 直接访问数据库

    • JDO (Java Data Object )技术

    • ,如Hibernate, Mybatis 等

  • JDBC是java访问数据库的基石,JDO、Hibernate、MyBatis等只是更好的包装JDBC。

1.3 JDBC介绍

  • JDBC(Java Database Connectivity)是一个(一组API),定义了访问数据库的标准Java类库,()可以使用这些类库访问数据库资源的方法方便。
  • JDBC它为访问不同数据库提供了一种,为开发者屏蔽一些细节。
  • JDBC的目标是使Java程序员使用JDBC任何连接都可以连接数据库系统使程序员不需要对特定数据库系统的特性有太多的了解,从而大大简化和加快了开发过程。
  • 如果没有JDBC,那么Java当程序访问数据库时:

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-CGQTW2G8-1657010009238)(尚硅谷_宋红康_JDBC.assets/1555575760234.png)]


  • 有了JDBC,Java当程序访问数据库时:

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-BsVJU2gn-1657010009238)(尚硅谷_宋红康_JDBC.assets/1555575981203.png)]


  • 总结如下:

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-kL6v5IGE-1657010009239)(尚硅谷_宋红康_JDBC.assets/1566741692804.png)]

1.4 JDBC体系结构

  • JDBC接口(API)包括两个层次:
    • :Java API,供应用程序开发人员使用抽象接口(连接数据库,执行SQL句子,结果)。
    • :Java Driver API,为开发商开发数据库驱动程序。

1.5 JDBC编程步骤

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-bBgE141P-1657010009239)(尚硅谷_宋红康_JDBC.assets/1565969323908.png)]

补充:ODBC(,开放式数据库连接)是微软Windows在平台下推出。用户只需在程序中调用ODBC API,由 ODBC 驱动程序将调用转换为特定数据库的调用请求。

第2章:获取数据库连接

2.1 要素一:Driver接口实现类

2.1.1 Driver接口介绍

  • java.sql.Driver 接口是所有 JDBC 驱动程序所需的接口。该接口提供给数据库制造商,不同的数据库制造商提供不同的实现。

  • 在程序中不需要直接访问 Driver 接口类别是驱动程序管理器类别(java.sql.DriverManager)去调用这些Driver实现。

    • Oracle的驱动:
    • mySql的驱动:

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-wt9RRtYQ-1657010009239)(尚硅谷_宋红康_JDBC.assets/1555576157618.png)]

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-mVwaT8iE-1657010009240)(尚硅谷_宋红康_JDBC.assets/1555576170074.png)]

  • 将上述jar包拷贝到Java在项目目录中,习惯于新建一个lib文件夹。

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-AuQ4M5pv-1657010009241)(尚硅谷_宋红康_JDBC.assets/1566134718955.png)]

在驱动jar上右键–>Build Path–>Add to Build Path

[外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-A89lvYgR-1657010009242)(尚硅谷_宋红康_JDBC.assets/1566134781682.png)]

注:如果是的话Dynamic Web Project(动态的web项目)是驱动jar放到WebContent(有的开发工具叫WebRoot)目录中的WEB-INF目录中的lib目录下即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJrfetpp-1657010009243)(尚硅谷_宋红康_JDBC.assets/1566135290460.png)]

2.1.2 加载与注册JDBC驱动

  • 加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),要加载的()传递给它 JDBC 驱动的类名

  • 注册驱动:DriverManager 驱动程序管理器负责驱动程序的管理

    • 通常不需要显式调用 DriverManager 类的 registerDriver() 方法注册驱动程序类的例子,因为 Driver 接口驱动程序类包含静态代码块,将在此静态代码块中调用 DriverManager.registerDriver() 注册自己实例的方法。MySQL的Driver实现类源代码:

      [外链图片存储失败,源站可能有防盗链机制,建议保存图片直接上传(img-W88YPbEG-1657010009244)(尚硅谷_宋红康_JDBC.assets/1566136831283.png)]/p>

2.2 要素二:URL

  • JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。

  • JDBC URL的标准由三部分组成,各部分间用冒号分隔。

    • :JDBC URL中的协议总是jdbc
    • :子协议用于标识一个数据库驱动程序
    • :一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了提供足够的信息。包含(对应服务端的ip地址)
  • 举例:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kInIP4rt-1657010009244)(尚硅谷_宋红康_JDBC.assets/1555576477107.png)]

    • MySQL的连接URL编写方式:

      • jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
      • jdbc:mysql://localhost:3306/atguigu
      • jdbc:mysql://localhost:3306/atguigu**?useUnicode=true&characterEncoding=utf8**(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
      • jdbc:mysql://localhost:3306/atguigu?user=root&password=123456
    • Oracle 9i的连接URL编写方式:

      • jdbc:oracle:thin:@主机名称:oracle服务端口号:数据库名称
      • jdbc:oracle:thin:@localhost:1521:atguigu
    • SQLServer的连接URL编写方式:

      • jdbc:sqlserver://主机名称:sqlserver服务端口号:DatabaseName=数据库名称

      • jdbc:sqlserver://localhost:1433:DatabaseName=atguigu

2.3 要素三:用户名和密码

  • user,password可以用“属性名=属性值”方式告诉数据库
  • 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接

2.4 数据库连接方式举例

2.4.1 连接方式一

	@Test
    public void testConnection1() { 
        
        try { 
        
            //1.提供java.sql.Driver接口实现类的对象
            Driver driver = null;
            driver = new com.mysql.jdbc.Driver();

            //2.提供url,指明具体操作的数据
            String url = "jdbc:mysql://localhost:3306/test";

            //3.提供Properties的对象,指明用户名和密码
            Properties info = new Properties();
            info.setProperty("user", "root");
            info.setProperty("password", "abc123");

            //4.调用driver的connect(),获取连接
            Connection conn = driver.connect(url, info);
            System.out.println(conn);
        } catch (SQLException e) { 
        
            e.printStackTrace();
        }
    }

说明:上述代码中显式出现了第三方数据库的API

2.4.2 连接方式二

	@Test
    public void testConnection2() { 
        
        try { 
        
            //1.实例化Driver
            String className = "com.mysql.jdbc.Driver";
            Class clazz = Class.forName(className);
            Driver driver = (Driver) clazz.newInstance();

            //2.提供url,指明具体操作的数据
            String url = "jdbc:mysql://localhost:3306/test";

            //3.提供Properties的对象,指明用户名和密码
            Properties info = new Properties();
            info.setProperty("user", "root");
            info.setProperty("password", "abc123");

            //4.调用driver的connect(),获取连接
            Connection conn = driver.connect(url, info);
            System.out.println(conn);

        } catch (Exception e) { 
        
            e.printStackTrace();
        }
    }

说明:相较于方式一,这里使用反射实例化Driver,不在代码中体现第三方数据库的API。体现了面向接口编程思想。

2.4.3 连接方式三

	@Test
    public void testConnection3() { 
        
        try { 
        
            //1.数据库连接的4个基本要素:
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "abc123";
            String driverName = "com.mysql.jdbc.Driver";

            //2.实例化Driver
            Class clazz = Class.forName(driverName);
            Driver driver = (Driver) clazz.newInstance();
            //3.注册驱动
            DriverManager.registerDriver(driver);
            //4.获取连接
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);
        } catch (Exception e) { 
        
            e.printStackTrace();
        }

    }

说明:使用DriverManager实现数据库的连接。体会获取连接必要的4个基本要素。

2.4.4 连接方式四

	@Test
    public void testConnection4() { 
        
        try { 
        
            //1.数据库连接的4个基本要素:
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "abc123";
            String driverName = "com.mysql.jdbc.Driver";

            //2.加载驱动 (①实例化Driver ②注册驱动)
            Class.forName(driverName);


            //Driver driver = (Driver) clazz.newInstance();
            //3.注册驱动
            //DriverManager.registerDriver(driver);
            /* 可以注释掉上述代码的原因,是因为在mysql的Driver类中声明有: static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } */


            //3.获取连接
            Connection conn = DriverManager.getConnection(url, user, password);
            System.out.println(conn);
        } catch (Exception e) { 
        
            e.printStackTrace();
        }

    }

说明:不必显式的注册驱动了。因为在DriverManager的源码中已经存在静态代码块,实现了驱动的注册。

2.4.5 连接方式五(最终版)

	@Test
    public  void testConnection5() throws Exception { 
        
    	//1.加载配置文件
        InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);
        
        //2.读取配置信息
        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");

        //3.加载驱动
        Class.forName(driverClass);

        //4.获取连接
        Connection conn = DriverManager.getConnection(url,user,password);
        System.out.println(conn);

    }

其中,配置文件声明在工程的src目录下:【jdbc.properties】

user=root
password=abc123
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver

说明:使用配置文件的方式保存配置信息,在代码中加载配置文件

①实现了代码和数据的分离,如果需要修改配置信息,直接在配置文件中修改,不需要深入代码 ②如果修改了配置信息,省去重新编译的过程。

第3章:使用PreparedStatement实现CRUD操作

3.1 操作和访问数据库

  • 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接。

  • 在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:

    • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
    • PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
    • CallableStatement:用于执行 SQL 存储过程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-opfYpNIO-1657010009245)(尚硅谷_宋红康_JDBC.assets/1566573842140.png)]

3.2 使用Statement操作数据表的弊端

  • 通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。

  • Statement 接口中定义了下列方法用于执行 SQL 语句:

    int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE
    ResultSet executeQuery(String sql):执行查询操作SELECT
    
  • 但是使用Statement操作数据表存在弊端:

  • SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。

  • 对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。

  • 代码演示:

public class StatementTest { 
        

	// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
	@Test
	public void testLogin() { 
        
		Scanner scan = new Scanner(System.in);

		System.out.print("用户名:");
		String userName = scan.nextLine();
		System.out.print("密 码:");
		String password = scan.nextLine();

		// SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '='1' or '1' = '1';
		String sql = "SELECT user,password FROM user_table WHERE USER = '" + userName + "' AND PASSWORD = '" + password
				+ "'";
		User user = get(sql, User.class);
		if (user != null) { 
        
			System.out.println("登陆成功!");
		} else { 
        
			System.out.println("用户名或密码错误!");
		}
	}

	// 使用Statement实现对数据表的查询操作
	public <T> T get(String sql, Class<T> clazz) { 
        
		T t = null;

		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		try { 
        
			// 1.加载配置文件
			InputStream is = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
			Properties pros = new Properties();
			pros.load(is);

			// 2.读取配置信息
			String user = pros.getProperty("user");
			String password = pros.getProperty("password");
			String url = pros.getProperty("url");
			String driverClass = pros.getProperty("driverClass");

			// 3.加载驱动
			Class.forName(driverClass);

			// 4.获取连接
			conn = DriverManager.getConnection(url, user, password);

			st = conn.createStatement();

			rs = st.executeQuery(sql);

			// 获取结果集的元数据
			ResultSetMetaData rsmd = rs.getMetaData();

			// 获取结果集的列数
			int columnCount = rsmd.getColumnCount();

			if (rs.next()) { 
        

				t = clazz.newInstance();

				for (int i = 0; i < columnCount; i++) { 
        
					// //1. 获取列的名称
					// String columnName = rsmd.getColumnName(i+1);

					// 1. 获取列的别名
					String columnName = rsmd.getColumnLabel(i + 1);

					// 2. 根据列名获取对应数据表中的数据
					Object columnVal = rs.getObject(columnName);

					// 3. 将数据表中得到的数据,封装进对象
					Field field = clazz.getDeclaredField(columnName);
					field.setAccessible(true);
					field.set(t, columnVal);
				}
				return t;
			}
		} catch (Exception e) { 
        
			e.printStackTrace();
		} finally { 
        
			// 关闭资源
			if (rs != null) { 
        
				try { 
        
					rs.close();
				} catch (SQLException e) { 
        
					e.printStackTrace();
				}
			}
			if (st != null) { 
        
				try { 
        
					st.close();
				} catch (SQLException e) { 
        
					e.printStackTrace();
				}
			}

			if (conn != null) { 
        
				try { 
        
					conn.close();
				} catch (SQLException e) { 
        
					e.printStackTrace();
				}
			}
		}

		return null;
	}
}

综上:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HKaog7R3-1657010009246)(尚硅谷_宋红康_JDBC.assets/1566569819744.png)]

3.3 PreparedStatement的使用

3.3.1 PreparedStatement介绍

  • 可以通过调用 Connection 对象的 方法获取 PreparedStatement 对象

  • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

3.3.2 PreparedStatement vs Statement

  • 代码的可读性和可维护性。

    • DBServer会对语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
    • 在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
    • (语法检查,语义检查,翻译成二进制命令,缓存)
  • PreparedStatement 可以防止 SQL 注入

3.3.3 Java与SQL对应数据类型转换表

Java类型 SQL类型
boolean BIT
byte TINYINT
short SMALLINT
int INTEGER
long BIGINT
String CHAR,VARCHAR,LONGVARCHAR
byte array BINARY , VAR BINARY
java.sql.Date DATE
java.sql.Time TIME
java.sql.Timestamp TIMESTAMP

3.3.4 使用PreparedStatement实现增、删、改操作

	//通用的增、删、改操作(体现一:增、删、改 ; 体现二:针对于不同的表)
	public void update(String sql,Object ... args){ 
        
		Connection conn = null;
		PreparedStatement ps = null;
		try { 
        
			//1.获取数据库的连接
			conn = JDBCUtils.getConnection();
			
			//2.获取PreparedStatement的实例 (或:预编译sql语句)
			ps = conn.prepareStatement(sql);
			//3.填充占位符
			for(int i = 0;i < args.length;i++){ 
        
				ps.setObject(i + 1, args[i]);
			}
			
			//4.执行sql语句
			ps.execute();
		} catch (Exception e) { 
        
			
			e.printStackTrace();
		}finally{ 
        
			//5.关闭资源
			JDBCUtils.closeResource(conn, ps);
			
		}
	}

3.3.5 使用PreparedStatement实现查询操作

	// 通用的针对于不同表的查询:返回一个对象 (version 1.0)
	public <T> T getInstance(Class<T> clazz, String sql, Object... args) { 
        

		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try { 
        
			// 1.获取数据库连接
			conn = JDBCUtils.getConnection();

			// 2.预编译sql语句,得到PreparedStatement对

标签: 02重载连接器he

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台