手动实现与数据库的连接
原始的连接方案:
1 @Test 2 public void testConnectin1() { 3 try { 4 // 1.创建数据库驱动中对java.sql.Driver抽象类的实现类(即:Driver)的实例化对象 5 Driver driver = new com.mysql.cj.jdbc.Driver(); 6 // 2.提供connection方法的参数:url,指明具体操作的数据 7 String url = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"; 8 // 3.提供connection方法的参数:info,即Properties类的对象,指明用户名和密码 9 Properties info = new Properties(); 10 info.setProperty("user", "root"); 11 info.setProperty("password", "password"); 12 // 4.通过调用Driver实现类对象的connection方法获取数据库连接 13 Connection conn = driver.connect(url, info); 14 System.out.println(conn); 15 } catch (SQLException e) { 16 e.printStackTrace(); 17 } 18 }
可优化的地方:第一步显式地使用了第三方的数据库API(即:Driver),因而不具备良好的可移植性和通用性。
改进方案一:可以通过反射的方式动态的创建指定类的实例化对象
1 @Test 2 public void testConnection2() { 3 try { 4 // 1. 通过反射的方式来创建一个指定类(com.mysql.cj.jdbc.Driver)的实例化对象 5 // 获取了Class类的对象 6 Class cla = Class.forName("com.mysql.cj.jdbc.Driver"); 7 // 通过Class的实例来创建指定类的实例化对象 8 Driver driver = (Driver) cla.newInstance(); 9 // 2. 提供connection方法的参数:url,指明具体操作的数据 10 String url = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"; 11 // 3.提供connection方法的参数:info,即Properties类的对象,指明用户名和密码 12 Properties info = new Properties(); 13 info.setProperty("user", "root"); 14 info.setProperty("password", "password"); 15 // 4.通过调用Driver实现类对象的connection方法获取数据库连接 16 Connection conn = driver.connect(url, info); 17 System.out.println(conn); 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } 21 }
改进方案二:使用DriverManager(驱动程序管理器类)替换Driver类
1 @Test 2 public void testConnection3() { 3 try { 4 // 1. 提供getConnection方法的三个基本参数: 5 String url = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"; 6 String user = "root"; 7 String password = "password"; 8 // 2. 通过反射的方式来创建一个指定类(com.mysql.cj.jdbc.Driver)的实例化对象 9 Class cla = Class.forName("com.mysql.cj.jdbc.Driver"); 10 Driver driver = (Driver) cla.newInstance(); 11 // 3. 注册驱动 12 DriverManager.registerDriver(driver); 13 // 4. 通过DriverManager获取数据库连接 14 Connection conn = DriverManager.getConnection(url, user, password); 15 System.out.println(conn); 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } 19 }
改进方案三:
因为在mysql的驱动中可以发现对 java.sql.Driver 抽象类的实现Driver类中声明有以下的静态代码块:
1 static { 2 try { 3 DriverManager.registerDriver(new Driver()); 4 } catch (SQLException var1) { 5 throw new RuntimeException("Can't register driver!"); 6 } 7 }
该代码块在我们加载Driver类时执行( Class.forName("com.mysql.cj.jdbc.Driver") )帮我们完成注册驱动。
因此我们不需要自己重复的进行驱动的注册。
1 @Test 2 public void testConnection4() { 3 try { 4 // 1. 提供getConnection方法的三个基本参数: 5 String url = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8"; 6 String user = "root"; 7 String password = "password"; 8 // 2. 通过反射的方式来创建一个指定类(com.mysql.cj.jdbc.Driver)的实例化对象 9 Class.forName("com.mysql.cj.jdbc.Driver"); 10 // 3. 通过DriverManager获取数据库连接 11 Connection conn = DriverManager.getConnection(url, user, password); 12 System.out.println(conn); 13 } catch (Exception e) { 14 e.printStackTrace(); 15 } 16 }
问题:用于连接的一些基本参数嵌入在代码中不利于代码的维护
最终方案:将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
将代码中的四个基本参数存放在工程的src目录下单独的 jdbc.properties 文件中:
1 user=root 2 password=password 3 url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8 4 driverClass=com.mysql.cj.jdbc.Driver
1 @Test 2 public void testConnerction() { 3 try { 4 // 1.加载配置文件(使用getResourceAsStream加载src目录下的配置文件) 5 // ClassLoader.getSystemClassLoader() 和 类名.class.getClassLoader(),两种方式都可以获取系统类加载器 6 // 方式一:调用运行时类的属性(.class)来获取Class对象 7 InputStream is = ConnectionTestCopy.class.getClassLoader().getResourceAsStream("jdbc.properties"); 8 // 方式二:ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties") 9 Properties pros = new Properties(); 10 pros.load(is); 11 // 读取配置文件中的信息 12 String user = pros.getProperty("user"); 13 String password = pros.getProperty("password"); 14 String url = pros.getProperty("url"); 15 String driverClass = pros.getProperty("driverClass"); 16 // 加载驱动 17 Class.forName(driverClass); 18 // 获取连接 19 Connection conn = DriverManager.getConnection(url, user, password); 20 System.out.println(conn); 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } 24 }