JDBC 学习笔记

目录

 

一、JDBC简介

二、JDBC 的开发步骤

三、JDBC 的简单使用

四、抽取 JDBC 工具类

五、SQL 的注入(了解)

六、PreparedStatement 的简单使用

七、封装数据

八、Properties 配置文件

8.1 编写 jdbc.properties 文件

8.2 重写 JDBCUtils.java 

九、整篇博客用到的 Java 代码打包地址:


一、JDBC简介

JDBC(Java DataBase Connectivity, java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数据库提供统一访问,它由一组用 java 语言编写的类和接口组成。JDBC 提供了一个种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC 也是个商标名。

JDBC 学习笔记_第1张图片

如果我们在程序中使用 JDBC 的话,需要导入一个数据库驱动,这个驱动就是我们的连接接口,主要开发者调用对应的方法,设置好对应的数据,即可访问对应的数据库进行操作。

【准备数据】

CREATE TABLE product (
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(30),
	price DOUBLE,
	mark VARCHAR(100) 
);

INSERT INTO product(NAME, price, mark) VALUES ('凹凸曼', 19.5, '超帅的凹凸曼');
INSERT INTO product(NAME, price, mark) VALUES ('五粮液', 59.5, '快涨了的');
INSERT INTO product(NAME, price, mark) VALUES ('伊利牛奶', 3.5, '想长高嘛?');
INSERT INTO product(NAME, price, mark) VALUES ('小猪佩琪', 29.5, '社会人的标志');

二、JDBC 的开发步骤

1)注册驱动:主要告诉 JVM 我们的程序将要使用哪一种数据库

2)获取连接:使用 JDBC 中的类,获得数据库的连接对象 Connection

3)获得语句执行平台:通过 Connection 可以获取执行者对象,Statement、PreparedStatement.

4)执行 SQL 语句:使用执行者对象,向数据库中执行 SQL 语句,然后可以得到对应的接口,有单个结果,也可能有结果集 ResultSet。

5)处理结果

6)释放对象:关闭顺序:rs -> stmt 、ptmt -> conn

三、JDBC 的简单使用

@Test
public void fun1() throws Exception {
	// 1.注册驱动
	// 这里,其实是用到了反射的原理,通过给定类的名字,让程序自动去找对应的类
	// 然后执行得到对应实例
	Class.forName("com.mysql.jdbc.Driver");

	// 使用注册方法的时候,底层会注册两次,不推荐使用
	// DriverManager.registerDriver(new com.mysql.jdbc.Driver());

	// 2.获取连接:数据库地址、用户名、密码 Connection
	String url = "jdbc:mysql://localhost:3306/test";
	String user = "root";
	String password = "root";
	Connection conn = DriverManager.getConnection(url, user, password);

	// 3.获取执行者对象
	Statement stmt = conn.createStatement();

	// 4.准备 SQL 语句
	String sql = "select * from product";

	// 5.执行 SQL 语句
	ResultSet rs = stmt.executeQuery(sql);

	// 6.处理结果
	while (rs.next()) {
		int idStr = rs.getInt("id");
		String nameStr = rs.getString("name");
		double priceStr = rs.getDouble("price");
		String markStr = rs.getString("mark");
		System.out.println(idStr + "--" + nameStr + "--" + markStr);
	}

	// 7.关闭资源
	rs.close();
	stmt.close();
	conn.close();
}

四、抽取 JDBC 工具类

在实际开发中,我们经常会碰到一些重复的代码,比如在获取某些资源的时候,解析某些数据的时候,都是需要重复去做一些相似的动作,这个时候很有必要抽取这些重复的代码成一个工具类,方面后面的使用。

很明显,我们每次操作数据库的,都需要连接数据库和关闭数据库,所有我们可以把数据库的连接和关闭都给抽取出来,作为公共部分。

新建一个 JDBCUtil.java 类。

public class JDBCUtils {
	// 重构:一旦发现代码用起来不是很爽的时候,一直有重复动作,必须想把饭抽取出来一个新的
	public JDBCUtils() {
	}

	public static Connection conn;

	// 静态块:在类初始化之后,会加载一次
	// 一般情况,我们会将一些常用的数据,放在静态块中进行加载
	// 加载完成之后,后面如果想要用的话,直接就可以用
	// 优点是,只会创建一次,不会重复创建良妃性能
	static {
		try {
			// 1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 2.获取连接:数据库地址、用户名、密码 Connection
			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String password = "root";
			conn = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取 Connection 对象
	 */
	public static Connection getConnection() {
		return conn;
	}

	/**
	 * 释放资源
	 */
	public static void close(Statement stmt, Connection conn) {
		// 思路:在关闭资源之前,先要判断,到底有没有用到这个资源
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

}

改写上面的类:(可以发现抽出公共部分之后,以后每次写的代码都会大大减少)

@Test
public void fun2() throws Exception {
	// 1.获取数据库连接
	Connection conn = JDBCUtils.getConnection();

	// 2.准备 SQL 语句
	String sql = "select * from product";
	
	// 3.获取执行者对象
	Statement stmt = conn.createStatement();

	// 4.执行 SQL 语句
	ResultSet rs = stmt.executeQuery(sql);

	// 5.处理结果
	while (rs.next()) {
		int idStr = rs.getInt("id");
		String nameStr = rs.getString("name");
		double priceStr = rs.getDouble("price");
		String markStr = rs.getString("mark");
		System.out.println(idStr + "--" + nameStr + "--" + markStr);
	}

	// 6.关闭资源
	JDBCUtils.close(rs, stmt, conn);
}

五、SQL 的注入(了解)

SELECT * FROM product WHERE NAME = '伊利牛奶' AND price= 3.5

使用 PreparedStatement 对象,可以预防SQL 注入和提高 SQL 的预编译。

@Test
public void fun3() throws Exception {
	// 1.获取数据库连接
	Connection conn = JDBCUtils.getConnection();

	// 2. 获取执行者对象
	// 如果使用 Statement 的话,则有可能会被 SQL 注入破坏
	// Statement stmt = conn.createStatement();
	// 推荐使用 PreparedStatement,它是 Statement 的子类,
	// 可以预防 SQL 注入,而且还可以把我们的 SQL 语句进行预初始化

	// 3. 准备 SQL 语句
	String sql = "select * from product where NAME = ? and price = ?";
	PreparedStatement ptmt = conn.prepareStatement(sql);
	// 这里的 1和2 表示的 where 后面的第n个属性
	ptmt.setString(1, "伊利牛奶");
	ptmt.setDouble(2, 3.5);

	// 4. 执行 SQL 语句
	ResultSet rs = ptmt.executeQuery();

	// 5. 处理结果
	while (rs.next()) {
		int idStr = rs.getInt("id");
		String nameStr = rs.getString("NAME");
		String passStr = rs.getString("price");
		System.out.println(idStr + "--" + nameStr + "--" + passStr);
	}

	// 6. 关闭资源
	JDBCUtils.close(rs, ptmt, conn);
}

六、PreparedStatement 的简单使用

主要演示了“修改”功能,至于其他的功能,有时间再自己实践下。

@Test
public void fun4() throws Exception {

	// 1.获取数据库连接
	Connection conn = JDBCUtils.getConnection();

	// 2. 准备 SQL 语句
	String sql = "update product set name = ?, price = ? where id = ?";

	PreparedStatement ptmt = conn.prepareStatement(sql);

	ptmt.setString(1, "奥特曼");
	ptmt.setString(2, "49.8");
	ptmt.setInt(3, 1);

	// 3. 执行 SQL 语句
	// 此处的返回值是 int 类型,如果有一条数据发生改变的话,则返回 1
	int i = ptmt.executeUpdate();

	// 4. 处理结果
	if (i == 1) {
		System.out.println("恭喜你,修改成功了...");
	}

	// 6. 关闭资源
	JDBCUtils.close(ptmt, conn);
}

七、封装数据

如果要封装数据的话,则需要新建一个对应的 JavaBean 类

如果要提供一个 JavaBean 的话,需要满足三个条件:、

1)实现序列化接口

2)提供字段

3)提供字段对应的 get 和 set 方法

注意: JavaBean 的命名,最好和对应的数据表一致。主要为了更好体现类与表的映射关系。

public class Product {
	private int id;
	private String NAME;
	private double price;
	private String mark;
	
	public Product(int id, String nAME, double price, String mark) {
		super();
		this.id = id;
		NAME = nAME;
		this.price = price;
		this.mark = mark;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getNAME() {
		return NAME;
	}
	public void setNAME(String nAME) {
		NAME = nAME;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public String getMark() {
		return mark;
	}
	public void setMark(String mark) {
		this.mark = mark;
	}
}

查询所有数据: 

/**
 * 封装数据
 * @throws Exception
 */
@Test
public void fun5() throws Exception {
	
	// 1. 获取数据库连接
	Connection conn = JDBCUtils.getConnection();
	
	// 2. 准备 SQL 语句
	String sql = "select * from product";
	
	PreparedStatement ptmt = conn.prepareStatement(sql);
	
	// 3. 执行 SQL 语句
	ResultSet rs = ptmt.executeQuery();
	
	// 4. 创建一个集合,用来保存查询出来的对象实例
	// 菱形语法,在泛型中,用来指定集合中存储的内容类型
	List proList = new ArrayList();
	
	// 5. 处理结果
	while (rs.next()){
		// 5.1 获取目标对象的实例,可以通过有参构造器
		int id = rs.getInt("id");
		String name = rs.getString("name");
		double price = rs.getDouble("price");
		String mark = rs.getString("mark");
		Product pro = new Product(id, name, price, mark);
		proList.add(pro);
	}
	
	// 5.2 查看保存数据的集合
	for (Product pro : proList) {
		System.out.println("商品的名字是:" + pro.getNAME());
	}
	
	// 6. 关闭资源
	JDBCUtils.close(rs, ptmt, conn);
}

八、Properties 配置文件

在实际开发中,我们一般情况下,会把配置相关的信息,放在 xx.properties 中保存,并且使用。因为,以后代码有可能写的非常复杂,像一些不经常改动的东西,都建议抽取出来保存到配置文件中。当我们要用的时候,直接从配置文件中获取使用。当我们需要修改的时候,显示找到文件,然后就可以直接修改即可。很方便的。

一般情况下,都是写死的内容,不会经常改动的。

8.1 编写 jdbc.properties 文件

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

8.2 重写 JDBCUtils.java 

public class JDBCUtils2 {
	public JDBCUtils2() {
	}

	public static Connection conn;

	private static String driver;
	private static String url;
	private static String user;
	private static String password;

	static {
		try {
			// 0.加载配置文件,获取对应的信息
			readConfig();
			// 1.注册驱动
			Class.forName(driver);
			// 2.获取连接:数据库地址、用户名、密码 Connection
			conn = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 用来加载配置文件
	 * 
	 * source folder 在部署之后,他的路径就是 bin 路径,也就是 classes 类资源路径
	 * 
	 * @throws IOException
	 */
	public static void readConfig() throws IOException {
		// 1.找到文件,并且加载文件
		InputStream is = JDBCUtils2.class.getClassLoader().getResourceAsStream("jdbc.properties");
		System.out.println("is 的值:" + is);

		// 2.从文件中获取数据
		Properties pro = new Properties();

		// 3.通过输入流加载数据
		pro.load(is);

		// 4.当获取到数据之后,应该把数据赋值给上面的变量
		driver = pro.getProperty("driver");
		url = pro.getProperty("url");
		user = pro.getProperty("user");
		password = pro.getProperty("password");
	}

	/**
	 * 获取 Connection 对象
	 */
	public static Connection getConnection() {
		return conn;
	}

	/**
	 * 释放资源
	 */
	public static void close(Statement stmt, Connection conn) {
		// 思路:在关闭资源之前,先要判断,到底有没有用到这个资源
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void close(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

九、整篇博客用到的 Java 代码打包地址:

https://github.com/yyzheng1729/JDBC

你可能感兴趣的:(MyBatis)