基本概念 JDBC英文名为:Java Data Base Connectivity(Java数据库连接),官方解释它是Java编程语言和广泛的数据库之间独立于数据库的连接标准的Java API,根本上说JDBC是一种规范,它提供的接口,一套完整的,允许便捷式访问底层数据库。可以用JAVA来写不同类型的可执行文件:JAVA应用程序、JAVA Applets、Java Servlet、JSP等,不同的可执行文件都能通过JDBC访问数据库,又兼备存储的优势。简单说它就是Java与数据库的连接的桥梁或者插件,用Java代码就能操作数据库的增删改查、存储过程、事务等。
连接数据库 需要提前下载mysql-connector包,这个包提供了jdbc的各种基本操作。首先打开maven网站,选择合适的版本。网站:https://mvnrepository.com/artifact/mysql/mysql-connector-java
需要额外注意的是从mysql-connector-java 6开始,连接时需要指定时区serverTimezone。连接数据库的步骤是通过DriverManager的getConnection获取数据库的连接。通过Statement来执行SQL语句。Statement中的excute()是用来执行任意的SQL语句
选择jar包下载
然后新建一个正常的java项目,把jar包拖到项目的src目录下后右键add as lib添加到项目中去。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.eldpepar;import java.sql.*;public class ConnetMain { public static void main (String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT" , "root" , "123456" ); Statement statement = connection.createStatement()) { String sql = "CREATE TABLE student(id int, name VARCHAR(8), sex VARCHAR(2))" ; boolean query = statement.execute(sql); } catch (SQLException e) { System.out.println("SQLException" ); } } }
mysql-connector6之前需要手动注册驱动 示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package cn.itcast.jdbc1;import java.io.FileReader;import java.io.IOException;import java.net.URL;import java.sql.*;import java.util.Properties;public class JdbcDemo1 { public static void main (String[] args) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver" ); Properties pro = new Properties(); ClassLoader classLoader = JdbcDemo1.class.getClassLoader(); URL res = classLoader.getResource("jdbc.properties" ); String path = res.getPath(); System.out.println(path); try { pro.load(new FileReader(path)); String url = pro.getProperty("url" ); String user = pro.getProperty("user" ); String password = pro.getProperty("password" ); Connection conn = DriverManager.getConnection(url, user, password); String sql = "CREATE TABLE student(id int, name VARCHAR(8), sex VARCHAR(2))" ; Statement stmt = conn.createStatement(); boolean query = stmt.execute(sql); stmt.close(); conn.close(); } catch (IOException e) { e.printStackTrace(); } } }
基本SQL示例 其中如果需要执行多个添加语句,使用的是addBatch方法。Statement调用的是executeBatch方法。示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.eldpepar;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.Statement;public class DMLDemo { public static void main (String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT" , "root" , "123456" ); Statement statement = connection.createStatement()) { String sql = "INSERT INTO student(id,name,sex) VALUES(2,'王五','男')" ; int result = statement.executeUpdate(sql); if (result > 0 ) { System.out.println("添加成功" ); } } catch (SQLException e) { System.out.println(e.getMessage()); } } }
查询示例 示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.eldpepar;import java.sql.*;public class DMLDemo { public static void main (String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT" , "root" , "123456" ); Statement statement = connection.createStatement()) { ResultSet set = statement.executeQuery("SELECT * FROM employee" ); while (set.next()) { System.out.print(set.getInt(1 ) + "," + set.getString(2 ) + "," + set.getString(3 ) +"," + set.getInt(4 ) + "," + set.getInt(5 )); System.out.println(); } } catch (SQLException e) { System.out.println(e.getMessage()); } } }
映射对象 示例代码(正常方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.eldpepar;import java.sql.*;public class BeanDemo { public static void main (String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT" , "root" , "123456" ); Statement statement = connection.createStatement()) { ResultSet set = statement.executeQuery("SELECT * FROM student" ); while (set.next()){ Student student = new Student(set.getInt(1 ), set.getString(2 ), set.getString(3 )); student.say(); } } catch (SQLException e) { System.out.println(e.getMessage()); } } }class Student { Integer sid; String name; String sex; public Student (Integer sid, String name, String sex) { this .sid = sid; this .name = name; this .sex = sex; } public void say () { System.out.println("我叫:" +name+",学号为:" +sid+",我的性别是:" +sex); } }
示例代码(反射方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 package com.eldpepar;import java.lang.reflect.Constructor;import java.sql.*;public class BeanDemo { public static void main (String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT" , "root" , "123456" ); Statement statement = connection.createStatement()) { ResultSet set = statement.executeQuery("SELECT * FROM student" ); while (set.next()) { Student student = Student.convert(set, Student.class); if (student != null ) student.say(); } } catch (SQLException e) { System.out.println(e.getMessage()); } } }class Student { Integer sid; String name; String sex; public Student (Integer sid, String name, String sex) { this .sid = sid; this .name = name; this .sex = sex; } public void say () { System.out.println("我叫:" + name + ",学号为:" + sid + ",我的性别是:" + sex); } static <T> T convert (ResultSet set, Class<T> clazz) { try { Constructor<T> constructor = clazz.getConstructor(clazz.getConstructors()[0 ].getParameterTypes()); Class<?>[] param = constructor.getParameterTypes(); Object[] object = new Object[param.length]; for (int i = 0 ; i < param.length; i++) { object[i] = set.getObject(i + 1 ); if (object[i].getClass() != param[i]) throw new SQLException("错误的类型转换:" + object[i].getClass() + " -> " + param[i]); } return constructor.newInstance(object); } catch (ReflectiveOperationException | SQLException e) { e.printStackTrace(); return null ; } } }
PreparedStatement 使用正常的拼接SQL的方法,如果用户输入的是or 1=1这类必为真的SQL语句时,就存在SQL注入的风险,为了解决这类的问题,引入了PreparedStatement来处理这类的问题。PreparedStatement可以使用‘?’来替换相应的参数,能够有效的避免SQL注入
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.eldpepar;import java.sql.*;public class PsDemo { public static void main (String[] args) { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT" , "root" , "123456" ); PreparedStatement statement = connection.prepareStatement("INSERT INTO student(id,name,sex) VALUES(?,?,?)" )) { statement.setInt(1 ,3 ); statement.setString(2 , "赵云" ); statement.setString(3 , "男" ); System.out.println(statement); int res = statement.executeUpdate(); if (res > 0 ) { System.out.println("插入成功!" ); } } catch (SQLException e) { System.out.println(e.getMessage()); } } }
连接池 在执行JDBC的增删改查的操作时,如果每一次操作都来一次打开连接,操作,关闭连接,那么创建和销毁JDBC连接的开销就太大了。为了避免频繁地创建和销毁JDBC连接,我们可以通过连接池(Connection Pool)复用已经创建好的连接。这里以德鲁伊连接池为例。使用的版本是druid-1.2.4和mysql-connector-java-8.0.20
配置文件(druid.properties)
1 2 3 4 5 6 7 driverClassName =com.mysql.jdbc.Driverurl =jdbc:mysql://127.0 .0.1 :3306 /user?serverTimezone=GMT%2 B8&useUnicode=true &characterEncoding=utf8&autoReconnect=true &useSSL=false username =rootpassword =123456 initiolSize =5 maxActive =10 maxWait =3000
工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 package com.eldpepar;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;public class DruidUtils { private static DataSource ds; static { Properties pro = new Properties(); try { pro.load(DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties" )); ds = DruidDataSourceFactory.createDataSource(pro); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection () throws SQLException { return ds.getConnection(); } public static void close (Statement stmt, Connection conn) { close(null , stmt, conn); } 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(); } } } public static DataSource getDataSource () { return ds; } }
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.eldpepar;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;public class DruidDemo { public static void main (String[] args) { Connection conn = null ; PreparedStatement psmt = null ; try { conn = DruidUtils.getConnection(); String sql = "insert into student values(?,?,?)" ; psmt = conn.prepareStatement(sql); psmt.setInt(1 ,4 ); psmt.setString(2 ,"张三" ); psmt.setString(3 ,"男" ); int count = psmt.executeUpdate(); System.out.println(count); } catch (SQLException e) { System.out.println(e.getMessage()); } } }