day17_jdbc基础

1 什么是jdbc?

	使用java代码(程序)发送sql语句的技术,就是jdbc技术!!!!
2 使用jdbc发送sql前提
	登录数据库服务器(连接数据库服务器)
	数据库的IP地址
	端口
	数据库用户名
	密码
3 JDBC接口核心的API
java.sql.*   和  javax.sql.*
		|- Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。
			|- connect(url, properties):  连接数据库的方法。
					url: 连接数据库的URL 
						URL语法: jdbc协议:数据库子协议://主机:端口/数据库
						user: 数据库的用户名
						password: 数据库用户密码
		|- DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序
			|-registerDriver(driver)  : 向DriverManager注  册驱动类对象
			|-Connection getConnection(url,user,password);  获取连接对象
		|- Connection接口: 表示java程序和数据库的连接对象。
				|- Statement createStatement() : 创建Statement对象 
				创建一个 Statement 对象来将 SQL 语句发送到数据库。
				|- PreparedStatement prepareStatement(String sql)  创建PreparedStatement对象
				创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。
				|- CallableStatement prepareCall(String sql) 创建CallableStatement对象
				创建一个 CallableStatement 对象来调用数据库存储过程。
		|- Statement接口: 用于执行静态的sql语句,并返回它所生成结果的对象。
				|- int executeUpdate(String sql)  : 执行静态的更新sql语句(DDL,DML)
				|- ResultSet executeQuery(String sql)  :执行的静态的查询sql语句(DQL)
			|-PreparedStatement接口:用于执行预编译sql语句
					|- int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)
					|-ResultSet executeQuery()  : 执行预编译的查询sql语句(DQL)
				|-CallableStatement接口:用于执行存储过程的sql语句(call xxx)
						|-ResultSet executeQuery()  : 调用存储过程的方法
		|- ResultSet接口:用于封装查询出来的数据,  表示数据路结果集的数据表,通常通过执行查询数据库的语句生成
				|- boolean next() : 将光标移动到下一行
				|-getXX() : 获取列的值
Connection connect(String url, Properties info) 

          试图创建一个到给定 URL 的数据库连接。


代码表示:

/**
 * jdbc连接数据库
 * @author APPle
 *
 */
public class Demo1 {
	//连接数据库的URL
	private String url = "jdbc:mysql://localhost:3306/day17";
	                  // jdbc协议:数据库子协议:主机:端口/连接的数据库   //

	private String user = "root";//用户名
	private String password = "123";//密码	
	/**
	 * 第一种方法
	 * @throws Exception
	 */
	@Test
	public void test1() throws Exception{
		//1.创建驱动程序类对象
		Driver driver = new com.mysql.jdbc.Driver(); //新版本
		//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,不建议使用
		
		//设置用户名和密码
		Properties props = new Properties();
		props.setProperty("user", user);
		props.setProperty("password", password);
		
		//2.连接数据库,返回连接对象
		Connection conn = driver.connect(url, props);
		
		System.out.println(conn);
	}
	
	/**
	 * 使用驱动管理器类连接数据库(注册了两次,没必要)
	 * @throws Exception
	 */
	@Test
	public void test2() throws Exception{
		Driver driver = new com.mysql.jdbc.Driver();
		//Driver driver2 = new com.oracle.jdbc.Driver();
		//1.注册驱动程序(可以注册多个驱动程序)
		DriverManager.registerDriver(driver);
		//DriverManager.registerDriver(driver2);
		
		//2.连接到具体的数据库
		Connection conn = DriverManager.getConnection(url, user, password);
		System.out.println(conn);
		
	}
	
	/**
	 * (推荐使用这种方式连接数据库)
	 * 推荐使用加载驱动程序类  来 注册驱动程序 
	 * @throws Exception
	 */
	@Test
	public void test3() throws Exception{
		//通过得到字节码对象的方式加载静态代码块,从而注册驱动程序
		Class.forName("com.mysql.jdbc.Driver");
		//1.注册驱动程序(可以注册多个驱动程序)
		DriverManager.registerDriver(driver);
		//DriverManager.registerDriver(driver2);
		
		//2.连接到具体的数据库
		Connection conn = DriverManager.getConnection(url, user, password);
		System.out.println(conn);	
	}
}
//Driver driver = new com.mysql.jdbc.Driver();  --->Driver()的源代码是:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}
里面继承了implements java.sql.Driver,而里面还是用静态代码块java.sql.DriverManager.registerDriver(new Driver());创建一个Driver,所以只要加载Driver类就可以自动创建所以test2()重复注册了两次
4 使用Statement执行sql语句
4.1 执行DDL语句
/**
	 * 执行DDL语句(创建表)
	 */
	@Test
	public void test1(){
		Statement stmt = null;
		Connection conn = null;
		try {
			//1.驱动注册程序
			Class.forName("com.mysql.jdbc.Driver");
			
			//2.获取连接对象
			conn = DriverManager.getConnection(url, user, password);
			
			//3.创建Statement
			stmt = conn.createStatement();
			
			//4.准备sql
			String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))";
			
			//5.发送sql语句,执行sql语句,得到返回结果(int)
			int count = stmt.executeUpdate(sql);
			
			//6.输出
			System.out.println("影响了"+count+"行!");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			//7.关闭连接(顺序:后打开的先关闭)
			if(stmt!=null)
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			if(conn!=null)
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}
		}
	}

维护链接消耗内存,每走完一次就关闭一次链接,释放内存

创建一个工具类:
package gz.itcast.a_statement;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.management.RuntimeErrorException;

public class JdbcUtil {
	
		private static String user = "root";
		private static String url = "jdbc:mysql://localhost:3306/day17";
		private static String password="123";
	
		static {
			try {
				Class.forName("com.mysql.jdbc.Driver");
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("驱动程序注册出错");
			}
		}
	public static Connection getConnection(){
			try {
				Connection conn = DriverManager.getConnection(url, user, password);
				return conn;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}		
	}
	public static void close(Connection conn,Statement stmt){
		if(stmt!=null)
			try {
				stmt.close();
			} catch (SQLException e) {		
				e.printStackTrace();
				throw new RuntimeException(e);
			}	
		if(conn!=null)
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
	}
	public static void close(Connection conn,Statement stmt,ResultSet rs){
		if(rs!=null)
			try {
				rs.close();
			} catch (SQLException e) {		
				e.printStackTrace();
				throw new RuntimeException(e);
			}	
		if(stmt!=null)
			try {
				stmt.close();
			} catch (SQLException e) {		
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		if(conn!=null)
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
	}
}

4.2 执行DML语句
/**
 * 使用Statement执行DML语句
 * @author APPle
 *
 */
public class Demo2 {
	private String url = "jdbc:mysql://localhost:3306/day17";
	private String user = "root";
	private String password = "123";
	/**
	 * 增加
	 */
	@Test
	public void testInsert(){
		Connection conn = null;
		Statement stmt = null;
		try {
			//通过工具类获取连接对象
			conn = JdbcUtil.getConnection();
			
			//3.创建Statement对象
			stmt = conn.createStatement();
			
			//4.sql语句
			String sql = "INSERT INTO student(NAME,gender) VALUES('李四','女')";
			
			//5.执行sql
			int count = stmt.executeUpdate(sql);
			System.out.println("影响了"+count+"行");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			//关闭资源
			/*if(stmt!=null)
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}
			if(conn!=null)
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
					throw new RuntimeException(e);
				}*/
			JdbcUtil.close(conn, stmt);   //使用工具类里面的close方法
		}
	}
	/**
	 * 修改
	 */
	@Test
	public void testUpdate(){
		Connection conn = null;
		Statement stmt = null;
		//模拟用户输入
		String name = "陈六";
		int id = 3;
		try {
			/*//1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			
			//2.获取连接对象
			conn = DriverManager.getConnection(url, user, password);*/
			//通过工具类获取连接对象
			conn = JdbcUtil.getConnection();
			
			//3.创建Statement对象
			stmt = conn.createStatement();
			
			//4.sql语句
			String sql = "UPDATE student SET NAME='"+name+"' WHERE id="+id+"";
			
			System.out.println(sql);
			
			//5.执行sql
			int count = stmt.executeUpdate(sql);
			System.out.println("影响了"+count+"行");	
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			//关闭资源
			JdbcUtil.close(conn, stmt);
		}
	}
	/**
	 * 删除
	 */
	@Test
	public void testDelete(){
		Connection conn = null;
		Statement stmt = null;
		//模拟用户输入
		int id = 3;
		try {
			/*//1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			
			//2.获取连接对象
			conn = DriverManager.getConnection(url, user, password);*/
			//通过工具类获取连接对象
			conn = JdbcUtil.getConnection();
			
			//3.创建Statement对象
			stmt = conn.createStatement();
			
			//4.sql语句
			String sql = "DELETE FROM student WHERE id="+id+"";
			System.out.println(sql);
			
			//5.执行sql
			int count = stmt.executeUpdate(sql);
			System.out.println("影响了"+count+"行");	
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally{
			//关闭资源
			JdbcUtil.close(conn, stmt);
		}
	}
}


5使用PreparedStatement执行sql语句

public class Demo1 {

	/**
	 * 增加
	 */
	@Test
	public void testInsert() {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			//1.获取连接
			conn = JdbcUtil.getConnection();
			
			//2.准备预编译的sql
			String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)"; //?表示一个参数的占位符
			
			//3.执行预编译sql语句(检查语法)
			stmt = conn.prepareStatement(sql);
			
			//4.设置参数值
			/**
			 * 参数一: 参数位置  从1开始
			 */
			stmt.setString(1, "李四");
			stmt.setString(2, "男");
			
			//5.发送参数,执行sql
			int count = stmt.executeUpdate();
			System.out.println("影响了"+count+"行");
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt);
		}
	}
	
	/**
	 * 修改
	 */
	@Test
	public void testUpdate() {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			//1.获取连接
			conn = JdbcUtil.getConnection();
			
			//2.准备预编译的sql
			String sql = "UPDATE student SET NAME=? WHERE id=?"; //?表示一个参数的占位符
			
			//3.执行预编译sql语句(检查语法)
			stmt = conn.prepareStatement(sql);
			
			//4.设置参数值
			/**
			 * 参数一: 参数位置  从1开始
			 */
			stmt.setString(1, "王五");
			stmt.setInt(2, 9);
			
			//5.发送参数,执行sql
			int count = stmt.executeUpdate();
			System.out.println("影响了"+count+"行");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt);
		}
	}
	
	/**
	 * 删除
	 */
	@Test
	public void testDelete() {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			//1.获取连接
			conn = JdbcUtil.getConnection();
			
			//2.准备预编译的sql
			String sql = "DELETE FROM student WHERE id=?"; //?表示一个参数的占位符
			
			//3.执行预编译sql语句(检查语法)
			stmt = conn.prepareStatement(sql);
			
			//4.设置参数值
			/**
			 * 参数一: 参数位置  从1开始
			 */
			stmt.setInt(1, 9);
			
			//5.发送参数,执行sql
			int count = stmt.executeUpdate();
			System.out.println("影响了"+count+"行");
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt);
		}
	}
	
	/**
	 * 查询
	 */
	@Test
	public void testQuery() {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			//1.获取连接
			conn = JdbcUtil.getConnection();
			
			//2.准备预编译的sql
			String sql = "SELECT * FROM student"; 
			
			//3.预编译
			stmt = conn.prepareStatement(sql);
			
			//4.执行sql
			rs = stmt.executeQuery();
			
			//5.遍历rs
			while(rs.next()){
				int id = rs.getInt("id");
				String name = rs.getString("name");
				String gender = rs.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			//关闭资源
			JdbcUtil.close(conn,stmt,rs);
		}
	}
}

select * from student where id=?
传递的只是参数,当再次调用上面的语句时候不会再创建一个执行任务,因为上面已经有了一个,会提取缓冲区的已有的执行任务,直接传递参数即可,所以执行的效率变高了

PreparedStatement vs Statment
1)语法不同:PreparedStatement可以使用预编译的sql,而Statment只能使用静态的sql
2)效率不同: PreparedStatement可以使用sql缓存区,效率比Statment高
3)安全性不同: PreparedStatement可以有效防止sql注入,而Statment不能防止sql注入。

推荐使用PreparedStatement

模拟用户登录

-- 模拟用户登录
-- 用户表
CREATE TABLE users(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	PASSWORD VARCHAR(20)
)

INSERT INTO users(NAME,PASSWORD) VALUES('eric','123456');
INSERT INTO users(NAME,PASSWORD) VALUES('rose','654321');

SELECT * FROM users;

-- 登录成功:用户输入的用户名和密码和users表的某条记录匹配
-- 登录失败:  找不到匹配的数据
SELECT * FROM users WHERE NAME='eric' AND PASSWORD='123456';

SELECT * FROM users;

SELECT * FROM users WHERE 1=1; -- 1=1 表示恒成立(永远成立,永远真)

-- sql注入
SELECT * FROM users WHERE NAME='eric' OR 1=1 -- 'and password='123456';


-- SELECT * FROM users WHERE NAME='eric';
-- SELECT * FROM users WHERE 1=1;
package gz.itcast.c_prepared;

import gz.itcast.util.JdbcUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import org.junit.Test;

/**
 * 模拟用户登录效果
 * @author APPle
 *
 */
public class Demo2 {
	//模拟用户输入
	//private String name = "ericdfdfdfddfd' OR 1=1 -- ";
	private String name = "eric";
	//private String password = "123456dfdfddfdf";
	private String password = "123456";

	/**
	 * Statment存在sql被注入的风险
	 */
	@Test
	public void testByStatement(){
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//获取连接
			conn = JdbcUtil.getConnection();
			
			//创建Statment
			stmt = conn.createStatement();
			
			//准备sql
			String sql = "SELECT * FROM users WHERE NAME='"+name+"' AND PASSWORD='"+password+"'";
			
			//执行sql
			rs = stmt.executeQuery(sql);
			
			if(rs.next()){
				//登录成功
				System.out.println("登录成功");
			}else{
				System.out.println("登录失败");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt ,rs);
		}
		
	}
	
	/**
	 * PreparedStatement可以有效地防止sql被注入
	 */
	@Test
	public void testByPreparedStatement(){
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			//获取连接
			conn = JdbcUtil.getConnection();
			
			String sql = "SELECT * FROM users WHERE NAME=? AND PASSWORD=?";
			
			//预编译
			stmt = conn.prepareStatement(sql);
			
			//设置参数
			stmt.setString(1, name);
			stmt.setString(2, password);
			
			//执行sql
			rs = stmt.executeQuery();
			
			if(rs.next()){
				//登录成功
				System.out.println("登录成功");
			}else{
				System.out.println("登录失败");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt ,rs);
		}
		
	}
}
使用 Statement会造成随意都可以登录进去,使用PreparedStatement可以有效地防止sql被注入

6 CallableStatement执行存储过程 

CallableStatement接口:用于执行存储过程的sql语句
6.1调用带有输入参数的存储过程
-- 创建一个存储过程
-- 带有输入参数的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById(IN sid INT)
BEGIN
	SELECT * FROM student WHERE id=sid;
END $
CALL pro_findById(1)  -- 使用java达到这个效果
-- 带有输出参数的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById2(IN sid INT,OUT sname VARCHAR(20))
BEGIN
	SELECT NAME INTO sname FROM student WHERE id=sid;
END $
CALL pro_findById2(2,@name);
SELECT @name;  -- 使用java达到输出值这个效果
/**
 * 使用CablleStatement调用存储过程
 * @author APPle
 *	
 */
public class Demo1 {

	/**
	 * 调用带有输入参数的存储过程
	 * CALL pro_findById(4);
	 */
	@Test
	public void test1(){
		Connection conn = null;
		CallableStatement stmt = null;
		ResultSet rs = null;
		try {
			//获取连接
			conn = JdbcUtil.getConnection();
			
			//准备sql
			String sql = "CALL pro_findById(?)"; //可以执行预编译的sql
			
			//预编译
			stmt = conn.prepareCall(sql);
			
			//设置输入参数
			stmt.setInt(1, 6);
			
			//发送参数
			rs = stmt.executeQuery(); //注意: 所有调用存储过程的sql语句都是使用executeQuery方法执行!!!
			
			//遍历结果
			while(rs.next()){
				int id = rs.getInt("id");
				String name = rs.getString("name");
				String gender = rs.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt ,rs);
		}
	}
	
	/**
	 * 执行带有输出参数的存储过程
	 * CALL pro_findById2(5,@NAME);
	 */
	@Test
	public void test2(){
		Connection conn = null;
		CallableStatement stmt = null;
		ResultSet rs = null;
		try {
			//获取连接
			conn = JdbcUtil.getConnection();
			//准备sql
			String sql = "CALL pro_findById2(?,?)"; //第一个?是输入参数,第二个?是输出参数
			
			//预编译
			stmt = conn.prepareCall(sql);
			
			//设置输入参数
			stmt.setInt(1, 6);
			//设置输出参数(注册输出参数)
			/**
			 * 参数一: 参数位置
			 * 参数二: 存储过程中的输出参数的jdbc类型    VARCHAR(20)
			 */
			stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
			
			//发送参数,执行
			stmt.executeQuery(); //结果不是返回到结果集中,而是返回到输出参数中
			
			//得到输出参数的值
			/**
			 * 索引值: 预编译sql中的输出参数的位置
			 */
			String result = stmt.getString(2); //getXX方法专门用于获取存储过程中的输出参数
			
			System.out.println(result);

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} finally {
			JdbcUtil.close(conn, stmt ,rs);
		}
	}
}
void registerOutParameter(int parameterIndex, int sqlType)    :按顺序位置 parameterIndex 将 OUT 参数注册为 JDBC 类型 sqlType。
7类路径读取
如果工具类在别的地方使用,则改变的会是url、user、password、Class.forName("com.mysql.jdbc.Driver")这些参数,所以要将这些信息写入到配置文件里面

所以新建配置文件db.properties

url=jdbc:mysql://localhost:3306/day17
user=root
password=123
driverClass=com.mysql.jdbc.Driver
在java文件里面使用工具类
package gz.itcast.util;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.management.RuntimeErrorException;

public class JdbcUtil {
	
		private static String user = null;
		private static String url = null;
		private static String password=null;
		private static String driverClass = null;
	
		static {
			try {
				Properties props = new Properties();
				FileInputStream in = new FileInputStream("./src/db.properties");
				props.load(in);
				//读取信息
				url = props.getProperty("url");
				user = props.getProperty("user");
				password = props.getProperty("password");
				driverClass = props.getProperty("driverClass");
				
				System.out.println(url);
				System.out.println(user);
				System.out.println(password);
				System.out.println(driverClass);
				
				//注册驱动程序
				Class.forName(driverClass);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("驱动程序注册出错");
			}
		}
	public static Connection getConnection(){
		
			
			try {
				Connection conn = DriverManager.getConnection(url, user, password);
				return conn;
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw new RuntimeException(e);
			}
	
		
	}
	public static void close(Connection conn,Statement stmt){
		if(stmt!=null)
			try {
				stmt.close();
			} catch (SQLException e) {		
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		
		if(conn!=null)
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
	}
	public static void close(Connection conn,Statement stmt,ResultSet rs){
		if(rs!=null)
			try {
				rs.close();
			} catch (SQLException e) {		
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		
		if(stmt!=null)
			try {
				stmt.close();
			} catch (SQLException e) {		
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		
		if(conn!=null)
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
	}

}


FileInputStream in = new FileInputStream("./src/db.properties");放在java项目里面是没有问题的,但是放在web项目里面就不行。
新建一个Servlet文件通过浏览器访问工具类里面数据里面链接情况

package gz.itcast.util;

import java.io.IOException;
import java.sql.Connection;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestPath extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//连接数据库
		//获取连接
		Connection conn = JdbcUtil.getConnection();
		System.out.println(conn);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

. 代表java命令运行的目录
 在java项目下,. java命令的运行目录从项目的根目录开始
 在web项目下,  . java命令的而运行目录从tomcat/bin目录开始
 放在web里面会提示:java.io.FileNotFoundException: .\src\db.properties (系统找不到指定的路径。)
FileInputStream in = new FileInputStream("./src/db.properties");  这一句提示错误, 所以不能使用点.

加入在tomcat/bin里面新建一个文件夹为src,放入db.properties文件,将会读取出:
jdbc:mysql://localhost:3306/day17
root
123
com.mysql.jdbc.Driver
com.mysql.jdbc.JDBC4Connection@12746ad0
但是并不是每一个tomcat里面都会有src文件目录,所以不能使用
使用类路径的读取方式
在java项目下,classpath的根目录从bin目录开始
在web项目下,classpath的根目录从WEB-INF/classes目录开始
/ : 斜杠表示classpath的根目录
类路径:
拿到一个类的字节码对象(通常是使用当前类的class)
java中源代码在src里面编译都早bin目录里面
在web项目下,classpath的根目录从WEB-INF/classes目录开始
刚好文件再java中在bin里面,在web里面在classes里面都是在根目录里面,所以直接是/db.properties
(javah和web里面都会的通用)

package gz.itcast.util;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * jdbc工具类
 * @author APPle
 *
 */
public class JdbcUtil {
	private static String url = null;
	private static String user = null;
	private static String password = null;
	private static String driverClass = null;
	
	/**
	 * 静态代码块中(只加载一次)
	 */
	static{
		try {
			//读取db.properties文件
			Properties props = new Properties();
			/**
			 *  . 代表java命令运行的目录
			 *  在java项目下,. java命令的运行目录从项目的根目录开始
			 *  在web项目下,  . java命令的而运行目录从tomcat/bin目录开始
			 *  所以不能使用点.
			 */
			//FileInputStream in = new FileInputStream("./src/db.properties");
			
			/**
			 * 使用类路径的读取方式
			 *  / : 斜杠表示classpath的根目录
			 *     在java项目下,classpath的根目录从bin目录开始
			 *     在web项目下,classpath的根目录从WEB-INF/classes目录开始
			 */
			InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");
			
			//加载文件
			props.load(in);
			//读取信息
			url = props.getProperty("url");
			user = props.getProperty("user");
			password = props.getProperty("password");
			driverClass = props.getProperty("driverClass");
			
			
			//注册驱动程序
			Class.forName(driverClass);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("驱程程序注册出错");
		}
	}

	/**
	 * 抽取获取连接对象的方法
	 */
	public static Connection getConnection(){
		try {
			Connection conn = DriverManager.getConnection(url, user, password);
			return conn;
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	
	/**
	 * 释放资源的方法
	 */
	public static void close(Connection conn,Statement stmt){
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	
	public static void close(Connection conn,Statement stmt,ResultSet rs){
		if(rs!=null)
			try {
				rs.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new RuntimeException(e1);
			}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值