一、数据库的连接

1. 引入JDBC驱动程序

1.1 如何获取驱动程序

驱动程序由数据库提供商提供下载。
MySQL 的驱动下载地址:http://dev.mysql.com/downloads/
依次点击 Connector/J -> Platform Independent ,如然后下载下面那个


1.2 如何在Java project 项目应用中添加数据库驱动 jar

① 把下载好的mysql-connector-j-8.0.31.jar拷贝到该项目中

ps:这里的lib文件夹是自己创建的(也可不创建)

② 然后点击Add as Library -> OK,把其添加到项目类路径下

这样就表示成功了

2. 连接操作

2.1 方式一:
@Testpublic void testConnection1() throws SQLException {//获取Driver实现类对象Driver driver = new com.mysql.cj.jdbc.Driver();//jdbc:mysql协议//localhost:ip地址//3306: 默认端口//student_attendance_system: 数据库名称String url = "jdbc:mysql://localhost:3306/student_attendance_system";Properties info = new Properties();//将用户名和密码封装在Propertyinfo.setProperty("user", "root");info.setProperty("password", "0915");Connection conn = driver.connect(url, info);System.out.println(conn);}
2.2 方式二:队方式一的迭代(目的:为了使程序不出现第三方的API,使得程序有更好的移植性)
@Testpublic void testConnection2() throws Exception {//1.获取Driver实现类对象Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");Driver driver = (Driver) clazz.newInstance();//2. 提供数据库连接String url = "jdbc:mysql://localhost:3306/student_attendance_system";//3. 提供连接需要的用户名和密码Properties info = new Properties();info.setProperty("user", "root");info.setProperty("password", "0915");//4. 获取连接Connection conn = driver.connect(url, info);System.out.println(conn);}
2.3 方式三:使用DriverManager替换Driver
@Testpublic void testConnection3() throws Exception {//1. 获取Driver实现类对象Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");Driver driver = (Driver) clazz.newInstance();//2. 提供3个类的基本信息String url = "jdbc:mysql://localhost:3306/student_attendance_system";String user = "root";String password = "0915";//注册驱动DriverManager.registerDriver(driver);//获取连接Connection conn =DriverManager.getConnection(url, user, password);System.out.println(conn);}
2.4 方式4:可以只加载,不用显示的注册驱动(Driver)
@Testpublic void testConnection4() throws Exception {//1. 提供3个类的基本信息String url = "jdbc:mysql://localhost:3306/student_attendance_system";String user = "root";String password = "0915";//2. 加载DriverClass clazz = Class.forName("com.mysql.cj.jdbc.Driver"); //也可以省略,因为META-INF/service的java.sql.Driver已经做过了//相较于方式三,可以省略如下操作://Driver driver = (Driver) clazz.newInstance();//注册驱动//DriverManager.registerDriver(driver);//获取连接Connection conn =DriverManager.getConnection(url, user, password);System.out.println(conn);}
2.5 方式五:将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接

这里要在src文件夹下建立一个文件(jdbc.properties),可以其他名字,然后在该文件下输入数据库连接需要的属性
ps:一般连数据库用这种方式

文件内容:

driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/testuser=rootpassword=0915

连接代码:

@Testpublic void testConnection5() throws Exception {// 1. 读取配置文件的4个信息InputStream is = SqlConnectionTest.class.getClassLoader().getResourceAsStream("src/jdbc.properties");Properties pros = new Properties();pros.load(is);String user = pros.getProperty("user");String password = pros.getProperty("password");String url = pros.getProperty("url");String driver = pros.getProperty("driver");//2. 加载驱动Class.forName(driver);Connection conn = DriverManager.getConnection(url, user, password);System.out.println(conn);}

3. 拓展

一般在项目中,数据库连接用一个工具类来会更好,这样只要在用的时候,直接调用就好了。

工具类:

package src.Util;import src.SqlConnectionTest.SqlConnectionTest;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java.util.Properties;/** * @author XiaoQ * @create 2022-12-11 19:26 */public class JDBCUtils {/** * @Description 获取数据库的连接 * @return Connection * @author XiaoQ * @date 2022/12/11 20:22 */public static Connection getConnection() throws Exception {// 1. 读取配置文件的4个消息InputStream is = SqlConnectionTest.class.getClassLoader().getResourceAsStream("src/jdbc.properties");Properties pros = new Properties();pros.load(is);String user = pros.getProperty("user");String password = pros.getProperty("password");String url = pros.getProperty("url");String driver = pros.getProperty("driver");//2. 加载驱动Class.forName(driver);//3. 获取连接Connection conn = DriverManager.getConnection(url, user, password);return conn;}/** * @Description 关闭连接和Statement * @return * @author XiaoQ * @date 2022/12/11 20:25 */static public void closeResource(Connection conn, Statement ps){try {if(ps != null)ps.close();} catch (SQLException e) {throw new RuntimeException(e);}try {if(conn != null)conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}/** * @Description 关闭连接、Statement、ResultSet * @return* @author XiaoQ * @date 2022/12/12 1:51 */static public void closeResource(Connection conn, Statement ps, ResultSet res){try {if(ps != null)ps.close();} catch (SQLException e) {e.printStackTrace();}try {if(conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}try {if(res != null)res.close();} catch (SQLException e) {e.printStackTrace();}}}

二、数据库的操作

1. 数据库的增、删、改操作

1.1 普通的增加操作
@Testpublic void insertTest(){Connection conn = null;PreparedStatement ps = null;try {// 1. 读取配置文件的4个消息InputStream is = SqlConnectionTest.class.getClassLoader().getResourceAsStream("src/jdbc.properties");Properties pros = new Properties();pros.load(is);String user = pros.getProperty("user");String password = pros.getProperty("password");String url = pros.getProperty("url");String driver = pros.getProperty("driver");//2. 加载驱动Class.forName(driver);//3. 获取连接conn = DriverManager.getConnection(url, user, password);//System.out.println(conn);//4. 预编译sql语句,返回PreparedStatement的实例String sql = "insert into stu values(" />;ps = conn.prepareStatement(sql);//5. 填充占位符ps.setString(1, "2001");ps.setString(2, "小黑");ps.setString(3, "89");//6. 执行sql语句ps.execute();} catch (Exception e) {throw new RuntimeException(e);} finally {//7. 资源关闭try {if(ps != null)ps.close();} catch (SQLException e) {throw new RuntimeException(e);}try {if(ps != null)conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
1.2 使用工具类后普通的修改操作

工具类JDBCUtils具体细节上面有

 @Testpublic void updateTest(){Connection conn = null;PreparedStatement ps = null;try {//获取数据库连接conn = JDBCUtils.getConnection();//预编译sql语句,返回PreparedStatementString sql = "update stu set name = ? where id = ?";ps = conn.prepareStatement(sql);//填充占位符ps.setString(1, "小小");ps.setObject(2, "1003");//执行操作ps.execute();} catch (Exception e) {e.printStackTrace();} finally {//关闭资源JDBCUtils.closeResource(conn,ps);}}
1.3 通用操作(增、删、改)

操作

public static void update(String sql, Object ...args){Connection conn = null;PreparedStatement ps = null;try {//获取数据库连接conn = JDBCUtils.getConnection();//预编译sql语句,返回PreparedStatementps = conn.prepareStatement(sql);//填充占位符for(int i = 0; i < args.length; i++){ps.setObject(i + 1, args[i]);}//执行操作ps.execute();} catch (Exception e) {e.printStackTrace();} finally {//关闭资源JDBCUtils.closeResource(conn,ps);}}

测试

@Testpublic void commonUpdateTest(){//增加操作String sql = "insert into stu values(?, ?, ?)";update(sql, "1005", "小达", 89);//修改操作sql = "update stu set name = ? where id = ?";update(sql, "小朱", "1005");//删除操作sql = "delete from stu where id = ?";update(sql, "1005");}

2. 数据库的查询操作

2.1 对一个表的普通查询操作(基础不好或初学者用这个就够了,这个比较简单且比较好理解)
public void test1() {Connection conn = null;PreparedStatement ps = null;ResultSet resultSet = null;try {//获取数据库的连接conn = JDBCUtils.getConnection();//预编译sql语句String sql = "select * from stu where id = ?";ps = conn.prepareStatement(sql);//填充占位符ps.setObject(1, "2066");//执行,并返回结果集resultSet = ps.executeQuery();if(resultSet.next()){//获取列值String id = resultSet.getString(1); //获取第一个字段String name = resultSet.getString(2); //获取第二个字段int score = resultSet.getInt(3); //获取第三个字段//把列值封装到Student对象中Student stu = new Student(id, name, score);System.out.println(stu);}} catch (Exception e) {e.printStackTrace();} finally {//关闭连接JDBCUtils.closeResource(conn, ps, resultSet);}}
2.2 对一个表的通用查询操作

注意:针对于表的字段于类的属性名不相同的情况:

  1. 必须在声明sql语句时,使用类的属性名来给字段起别名
  2. 使用ResultSetMetaData时,需要用getColumnLabel()来替换getCoulmnName(),获取列的别名
    说明:如果sql语句没有给字段起别名,那么gewtColumnLabel()得到就是列名

操作

 public Student queryForStu(String sql, Object ...args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {//获取数据库连接conn = JDBCUtils.getConnection();//sql语句的预处理ps = conn.prepareStatement(sql);//占位符填充for(int i = 0; i < args.length; i++){ps.setObject(i + 1, args[i]);}//执行,并返回结果集rs = ps.executeQuery();//获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();//通过ResultSetMetaData获取结果集的列数int columnCount = rsmd.getColumnCount();if(rs.next()){Student stu = new Student();for(int i = 0; i < columnCount; i++){//获取列值Object columnValue = rs.getObject(i + 1);//getColumnName: 获取列的列名//getColumnLabel: 获取列的别名(推荐用这个,因为如果没查询起别名的,那么别名就是字段名)String columnName = rsmd.getColumnName(i + 1);//给stu对象指定的columnName属性,赋值为columnValue,通过反射//注意:如果该表的字段(这里指stu表)不和该类(这里指Student类)的属性对应相同,那么sql查询语句就要给//查询的字段起别名,防止反射后报错Field field = Student.class.getDeclaredField(columnName);//void setAccessible(boolean flag)//为反射对象设置可访问标志。flag为true表明屏蔽java语言的访问检查,使得对象的私有属性也可以被查询和设置field.setAccessible(true);//访问不符合访问权限对象的成员属性field.set(stu, columnValue);}return stu;}} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, ps, rs);}return null;}

测试

@Testpublic void testQueryForStu(){String sql = "select * from stu where id = ?";Student student = queryForStu(sql, "2066");System.out.println(student);sql = "select name from stu where id = ?";student = queryForStu(sql, "2001");System.out.println(student);}
2.3 针对不同表的查询,返回一条纪录(泛型)

操作:

/** * @Description 针对不同表的通用查询,返回一条记录 * @return T * @author XiaoQ * @date 2022/12/12 0:50 */public <T> T getInstance(Class<T> clazz, String sql, Object ...args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {//获取数据库连接conn = JDBCUtils.getConnection();//sql语句的预处理ps = conn.prepareStatement(sql);//占位符填充for(int i = 0; i < args.length; i++){ps.setObject(i + 1, args[i]);}//执行,并返回结果集rs = ps.executeQuery();//获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();//通过ResultSetMetaData获取结果集的列数int columnCount = rsmd.getColumnCount();if(rs.next()){T t = clazz.newInstance();for(int i = 0; i < columnCount; i++){//获取列值Object columnValue = rs.getObject(i + 1);//getColumnName: 获取列的列名//getColumnLabel: 获取列的别名(推荐用这个,因为如果没查询起别名的,那么别名就是字段名)String columnName = rsmd.getColumnLabel(i + 1);//给stu对象指定的columnName属性,赋值为columnValue,通过反射//注意:如果该表的字段(这里指stu表)不和该类(这里指Student类)的属性对应相同,那么sql查询语句就要给//查询的字段起别名,防止反射后报错Field field = clazz.getDeclaredField(columnName);//void setAccessible(boolean flag)//为反射对象设置可访问标志。flag为true表明屏蔽java语言的访问检查,使得对象的私有属性也可以被查询和设置field.setAccessible(true);//访问不符合访问权限对象的成员属性field.set(t, columnValue);}return t;}} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, ps, rs);}return null;}

测试

@Testpublic void test(){String sql = "select * from stu where id = ?";Student student = getInstance(Student.class, sql, "1001");System.out.println(student);sql = "select t_id id, t_name name, salary from teacher where t_id = ?";Teacher teacher = getInstance(Teacher.class, sql, "4563");System.out.println(teacher);}
2.4 针对不同表的通用查询,返回多条记录(泛型)

操作

/** * @Description 对不同表的通用查询,返回多条记录 * @return List * @author XiaoQ * @date 2022/12/12 1:00 */public <T>List<T> getForList(Class<T> clazz, String sql, Object ...args){Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {//获取数据库连接conn = JDBCUtils.getConnection();//sql语句的预处理ps = conn.prepareStatement(sql);//占位符填充for(int i = 0; i < args.length; i++){ps.setObject(i + 1, args[i]);}//执行,并返回结果集rs = ps.executeQuery();//获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();//通过ResultSetMetaData获取结果集的列数int columnCount = rsmd.getColumnCount();//创建集合对象ArrayList<T> list = new ArrayList<T>();while (rs.next()){T t = clazz.newInstance();//处理结果集一行数据中的每一列:给t对象指定的属性赋值for(int i = 0; i < columnCount; i++){//获取列值Object columnValue = rs.getObject(i + 1);//getColumnName: 获取列的列名//getColumnLabel: 获取列的别名(推荐用这个,因为如果没查询起别名的,那么别名就是字段名)String columnName = rsmd.getColumnLabel(i + 1);//给stu对象指定的columnName属性,赋值为columnValue,通过反射//注意:如果该表的字段(这里指stu表)不和该类(这里指Student类)的属性对应相同,那么sql查询语句就要给//查询的字段起别名,防止反射后报错Field field = clazz.getDeclaredField(columnName);//void setAccessible(boolean flag)//为反射对象设置可访问标志。flag为true表明屏蔽java语言的访问检查,使得对象的私有属性也可以被查询和设置field.setAccessible(true);//访问不符合访问权限对象的成员属性field.set(t, columnValue);}list.add(t);}return list;} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.closeResource(conn, ps, rs);}return null;}

测试

@Testpublic void test1(){String sql = "select * from stu";List<Student> list = getForList(Student.class, sql);list.forEach(System.out::println);sql = "select t_id id, t_name name, salary from teacher where salary < ?";List<Teacher> list1 = getForList(Teacher.class, sql, 1000);list1.forEach(System.out::println);}