获取数据库连接的方式 & Statement操作数据库的弊端
1.获取数据库连接的方式
TestConnection
package com.aff.connection; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import org.junit.Test; public class TestConnection { // 方式一 @Test public void testConnection() throws SQLException { // 获取Driver的实现类对象 Driver driver = new com.mysql.jdbc.Driver(); // jdbc:mysql 协议 // localhost ip地址 // 3306 默认mysql端口号 // test 数据库名 String url = "jdbc:mysql://localhost:3306/test"; // 用户名和密码封装在Properties Properties info = new Properties(); info.setProperty("user", "root"); info.setProperty("password", "123456"); Connection conn = driver.connect(url, info); System.out.println(conn); } // 方式二:对方式一的迭代,,在如下的程序中不出现第三方的api,使得程序具有更好的可移植性 @Test public void testConnection2() throws Exception { // 获取Driver实现类对象:使用反射 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance(); // 连接需要的数据库 String url = "jdbc:mysql://localhost:3306/test"; // 提供连接需要的用户名和密码 Properties info = new Properties(); info.setProperty("user", "root"); info.setProperty("password", "123456"); // 获取连接 Connection conn = driver.connect(url, info); System.out.println(conn); } // 方式三: 使用DriverManager管理 @Test public void testConnection3() throws Exception { // 获取Driver实现类的对象 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance(); // 提供三个连接的基本信息 String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "123456"; // 获取DriverManager的驱动 // 注册驱动 DriverManager.registerDriver(driver); // 获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); } // 方式四:在三的基础上优化 @Test public void testConnection4() throws Exception { // 1.提供三个连接的基本信息 String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "123456"; // 2. 加载驱动,mysql的Driver的实现类中,注册过了驱动 Class.forName("com.mysql.jdbc.Driver"); // 3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); } // 方式五:最终版,将数据库连接需要的4个信息声明在配置文件中,通过读取配置文件的方式连接数据库 /* * 好处:1.实现了数据与代码的分离,实现了解耦 * 2.如果需要修改配置信息,可以避免后程序重新打包 */ @Test public void testConnection5() throws Exception { // 1.读取配置文件中的4个基本信息,通过类加载器 InputStream is = TestConnection.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties pro = new Properties(); // 加载is这个文件 pro.load(is); // 读取其中的配置信息 String user = pro.getProperty("user"); String url = pro.getProperty("url"); String password = pro.getProperty("password"); String driverClass = pro.getProperty("driverClass"); // 2.加载驱动 Class.forName(driverClass); // 3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); System.out.println(conn); } }
2.Statement操作数据库的弊端:需要拼写sql语句,并且存在SQL注入的问题
示例:testLogin
package com.aff.connection; import java.io.InputStream; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import java.util.Scanner; import org.junit.Test; 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; } }
User
package com.aff.connection; public class User { private String user; private String password; public User() { } public User(String user, String password) { super(); this.user = user; this.password = password; } @Override public String toString() { return "User [user=" + user + ", password=" + password + "]"; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
All that work will definitely pay off