JDBC 速查手册
发布于: 2021 年 02 月 14 日
JDBC URL
JDBC URL 格式
jdbc:mysql://主机名称:mysql服务端口号(默认为3306)/数据库名称?参数1=值1&参数2=值2复制代码
如果 JDBC 程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8复制代码
也可以用“属性名=属性值”方式告诉数据库
jdbc:mysql://localhost:3306/test?user=root&password=123456复制代码
获取连接
注意:jar 包版本要和 MySQL 版本匹配,否则会连接不上。
方式一
直接使用第三方数据库的 API。
@Testpublic void testConnection1() throws Exception { // 获取 Driver 实现类对象 Driver driver = new com.mysql.jdbc.Driver();
// test:test数据库 String url = "jdbc:mysql://localhost:3306/test"; // 将用户名和密码封装在 Properties 中 Properties info = new Properties(); info.setProperty("user", "root"); info.setProperty("password", "abc123");
Connection conn = driver.connect(url, info); System.out.println(conn);}复制代码
方式二
不使用第三方的 API,使用反射实例化 Driver,体现了面向接口编程的思想,使得程序具有更好的可移植性。
@Testpublic void testConnection2() throws Exception { // 1. 获取 Driver 实现类对象:使用反射 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance();
// 2. 提供要连接的数据库 String url = "jdbc:mysql://localhost:3306/test";
// 3. 提供连接需要的用户名和密码 Properties info = new Properties(); info.setProperty("user", "root"); info.setProperty("password", "abc123");
// 4. 获取连接 Connection conn = driver.connect(url, info); System.out.println(conn);}复制代码
方式三
使用 DriverManager 替换 Driver。
@Testpublic void testConnection3() throws Exception { // 1. 获取 Driver 实现类的对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance();
// 2. 提供另外三个连接的基本信息: String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "abc123";
// 注册驱动 DriverManager.registerDriver(driver);
// 获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn);}复制代码
方式四
可以只是加载驱动,不用显式地注册驱动了。
@Testpublic void testConnection4() throws Exception { // 1. 提供三个连接的基本信息: String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "abc123"; // 2. 加载 Driver Class.forName("com.mysql.jdbc.Driver");
// 3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn);}复制代码
之所以可以只加载驱动,而不用显式地注册驱动,是因为在 MySQL 的 Driver 实现类中,存在如下的静态代码块:
static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); }}复制代码
方式五-最终版
将数据库连接需要的 4 个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接。这种方式的好处是:
实现了数据与代码的分离,即实现了解耦
如果需要修改配置文件信息即可,可以避免程序重新打包
public class ConnectionTest { @Test public void getConnection5() throws Exception{ // 1. 读取配置文件中的 4 个基本信息 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("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 driverClass = pros.getProperty("driverClass");
// 2. 加载驱动 Class.forName(driverClass);
// 3. 获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); }}复制代码
src/jdbc.properties 文件内容如下:
user=rootpassword=abc123url=jdbc:mysql://localhost:3306/testdriverClass=com.mysql.jdbc.Driver复制代码
注意:在 .properties 文件中,= 左右不要有空格。
执行 SQL 语句
Statement
使用 Statement 的弊端:需要拼写 SQL 语句,并且存在 SQL 注入的问题。
public class StatementTest { @Test public void testLogin() { Scanner scan = new Scanner(System.in);
System.out.print("用户名:"); String userName = scan.nextLine(); // 这里之所以用 nextLine(),而不是 next() 方法,是因为要从标准输入中读取:"1' OR "和"=1 OR '1' = '1'" 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 = ClassLoader.getSystemClassLoader().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; }}复制代码
划线
评论
复制
发布于: 2021 年 02 月 14 日阅读数: 29
版权声明: 本文为 InfoQ 作者【jiangling500】的原创文章。
原文链接:【http://xie.infoq.cn/article/296722491fa4a7cf91eb6fe75】。文章转载请联系作者。
jiangling500
关注
万丈高楼平地起,勿在浮沙筑高台! 2019.12.17 加入
一名IT从业者,熟悉Linux下C/C++,了解MySQL、Java等。











评论