Java连接数据库——JDBC

JDBC

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问
通过数据库厂家提供的Driver接口,连接数据库,通过不同数据库的驱动操作数据库

JDBC中的接口

常用接口:
1.Driver接口:用于注册驱动
	装载MySql驱动:Class.forName("com.mysql.jdbc.Driver"); 利用反射注册驱动
	装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");
	
2.Connection接口:与特定数据库的连接对象

3.Statement接口:用于执行静态SQL语句并返回它所生成结果的对象
	三种Statement类:
	Statement:由Connection接口的createStatement方法创建,用于发送简单的SQL语句(不带参数)
	PreparedStatement :继承自Statement接口,由preparedStatement创建,用于发送含有一个或多个参数的SQL语句。
						PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,所以我们一般都使用PreparedStatement。
	CallableStatement:继承自PreparedStatement接口,由方法prepareCall创建,用于调用存储过程
	
4.ResultSet接口:SQL语句结果集对象,提供对结果集处理的方法
使用后依次关闭对象及连接:ResultSet → Statement → Connection

使用JDBC的步骤

1.注册驱动(只注册一次)
2.建立数据库连接,需要数据库连接的参数
3.创建执行SQL语句的对象statement
		sql语句的增删改一般使用executeUpdate(sql)方法
		查询一般是executeQuery(sql)方法
4.处理执行结果
5.释放资源
public static void main(String[] args) throws ClassNotFoundException, SQLException {
		// 1.注册驱动	
		Class.forName("com.mysql.jdbc.Driver");// 反射注册驱动
		// 2.连接数据库,获取数据库连接对象
		String url = "jdbc:mysql://localhost:3306/test";
		String user = "root";
		String password = "123";
		Connection conn = DriverManager.getConnection(url, user, password);

		// 3.获得SQL语句执行对象
		Statement create = conn.createStatement();


		// 4.通过SQL执行对象执行sql语句
		// int date = create.executeUpdate("insert into sort(names,price,descs)插入操作
		// values('厨房用品',56,'测试')");
		ResultSet res = create.executeQuery("select * from sort");//查询操作

		// 5.显示处理结果的行数
		while (res.next()) {
			System.out.println(res.getInt("sid") + " " + res.getString("names") + " " + res.getDouble("price") + " "
					+ res.getString("descs"));
		}
		// 6.关闭资源
		res.close();
		create.close();// 关闭SQL执行对象
		conn.close();// 关闭数据库连接对象

	}

SQL注入

select * from person where name=? and password=?
有恶意用户输入参数1=1 or 等类似的参数让条件判断恒成立
所以不能使用字符串拼接将参数和SQL拼接
而是使用预编译的方式将参数以占位符的形式传入SQL中
使用预编译需要SQL操作对象是PreparedStatement(Statement接口的子类)
		// 1.注册驱动
		Class.forName("com.mysql.jdbc.Driver");// 反射注册驱动
		// 2.连接数据库,获取数据库连接对象
		String url = "jdbc:mysql://localhost:3306/test";
		String user = "root";
		String password = "123";
		Connection conn = DriverManager.getConnection(url, user, password);

		// 3.获得SQL语句执行对象
		String sql = "select * from sort where age > ?";
		PreparedStatement prepare = conn.prepareStatement(sql);
		prepare.setObject(1, 12);//将参数传入占位符
		//第一个参数是占位符的下标,从1开始
		//第二个参数是具体的参数值

		// 4.通过SQL执行对象执行sql语句
		ResultSet res = prepare.executeQuery("select * from sort");

		// 5.显示处理结果的行数
		while (res.next()) {
			System.out.println(res.getInt("sid") + " " + res.getString("names") + " " + res.getDouble("price") + " "
					+ res.getString("descs"));
		}
		// 6.关闭资源
		res.close();
		prepare.close();// 关闭SQL执行对象
		conn.close();// 关闭数据库连接对象

封装功能代码

数据库连接代码与资源关闭代码不会任意改变,可以抽取到工具类中
将数据库连接对象作为属性,使用静态代码块完成实例化
使用静态方法获取这个属性
使用静态方法关闭资源
public class JDBCutils {
	private static Connection conn;
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/test";
			String user = "root";
			String password = "123";
			conn = DriverManager.getConnection(url, user, password);
			System.out.println(conn);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static Connection getConnection() {
		return conn;
	}

	public static void closeConnection(Connection con, Statement s, ResultSet r) {
		if (con != null) {
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (s != null) {
			try {
				s.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (r != null) {
			try {
				r.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

获取连接对象与关闭资源就可以直接调用工具类
	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		Connection conn = JDBCutils.getConnection();
		PreparedStatement pre = conn.prepareStatement("select names from sort");
		ResultSet executeQuery = pre.executeQuery();
		while (executeQuery.next()) {
			System.out.println(executeQuery.getString("names"));
		}
		JDBCutils.closeConnection(conn, pre, executeQuery);
	}
关于数据库连接信息可以进一步封装为db.properties配置文件
将数据库连接需要的信息以键值形式写入配置文件
以Properties读取配置文件
public class JDBCPropertiesUtils {
	private static String driver;
	private static String url;
	private static String user;
	private static String password;
	private static Connection conn;
	
	static {
		try {
			readConfig();//数据库的配置信息的初始化
			Class.forName(driver);	
			conn = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void readConfig() throws IOException {
		InputStream resour = JDBCProperties.class.getClassLoader().getResourceAsStream("db.properties");
		//当前类的class对象获取class加载器获取资源加载的流
		Properties p = new Properties();
		p.load(resour);
		resour.close();
		driver = p.getProperty("driver");
		url = p.getProperty("url");
		user = p.getProperty("user");
		password = p.getProperty("password");
	}

JDBC的事务

设计数据库表的增删改操作时需要开启事务来配合
JDBC默认的事务处理行为是自动提交
JDBC是通过Connection对象进行事务管理
Connection.setAutoCommit() 设置自动提交,true为自动提交,false为手动提交

Connection.setAutoCommit(false) ;手动提交
SQL语句
Connection.commit();提交事务

Connection.rollback() 发生异常回滚事务

JDBC连接池

数据库连接的创建,销毁都非常销毁资源,可以防止线程池造一个数据库的连接池,存放一定数量的数据库连接
自定义数据池需要实现javax.sql.DataSource连接池接口
使用List集合存放多个连接的对象
初始时创建指定个数的连接对象放入连接池
获取连接时从连接池移除一个连接并返回给调用者
销毁连接时将连接添加到连接池(不是真正的销毁)
public class MyDataSource implements DataSource{
	//1.创建1个容器用于存储Connection对象
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	
	//2.初始时创建5个连接放到容器中去
	static{
		for (int i = 0; i < 5; i++) {
			Connection conn = JDBCUtils.getConnection();
			pool.add(conn);
		}
	}
	/**
	 * 重写获取连接的方法
	 */
	@Override
	public Connection getConnection() throws SQLException {
		Connection conn = null;
		//3.使用前先判断连接池是否还有连接
		if(pool.size()==0){
			//4.池子里面没有,我们再创建一些
			for (int i = 0; i < 5; i++) {
				conn = JDBCUtils.getConnection();
				pool.add(conn);
			}
		}
		//5.从池子里面获取一个连接对象Connection
		conn = pool.remove(0);
		return conn;
	}
	
	/**
	 * 归还连接对象到连接池中去
	 */
	public void backConnection(Connection conn){
		pool.add(conn);
	}
对Connection连接对象的close进行增强,当执行close方法时默认去执行连接池的返回对象到连接池的方法
自定义MyConnection实现Connection
重写close方法
在连接池中创建MyConnection对象代替Connection
public class MyConnection implements Connection{
 
	private Connection conn;
	private List<Connection> list;
	public MyConnection(Connection conn,List<Connection> list) {
		this.conn = conn;
		this.list = list;
	}
 	
	@Override//重写close方法:将连接对象添加到连接池
	public void close() throws SQLException {
		list.add(conn);
	}

连接池创建连接对象
public class MyDataSource implements DataSource{
	@Override
	// 获得连接的方法:
	public Connection getConnection() throws SQLException {
		if(list.size() <= 0){
			for(int i=1;i<=3;i++){
				Connection conn = JDBCUtils.getConnection();
				MyConnection myConn = new MyConnection(conn, list);
				list.add(myConn);
			}	
		}
		Connection conn = list.remove(0);
		//增强后的连接对象
		MyConnection myConn = new MyConnection(conn, list);
		return myConn;
	}

常见的开源的数据库连接池:
DBCP(DataBase connection pool)数据库连接池是apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件
	单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,目前使用它的开源项目有Hibernate,Spring等

DBUtils

commons-dbutils是一个对JDBC进行简单封装的开源工具类库
可以配合数据连接池使用
DbUtils最主要的就两个,QueryRunner类和ResultSetHandler接口
QueryRunner类这个类主要用于提供各种重载形式的batch方法,query方法和update 方法
ResultSetHandler接口用于映射结果集

QueryRunner对象需要一个数据源对象
public class DBCPUtils {//DBCP数据源工具类
	private static DataSource dataSource;
	static {
		try {
			// 1.加载找properties文件输入流
			InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("db.properties");
			// 2.加载输入流
			Properties props = new Properties();
			props.load(is);
			// 3.创建数据源
			dataSource = BasicDataSourceFactory.createDataSource(props);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static DataSource getDataSource() {
		return dataSource;
	}
使用DBUtils操作SQL,解析结果集
查询单条记录
BeanHandler 映射单条记录对应的Bean的类型
public static void main(String[] args) throws SQLException {
		
		DataSource ds = DBCPUtils.getDataSource();
		QueryRunner qr = new QueryRunner(ds);
		String sql = "select * from student where id=?";
		//查询单条记录,参数1——SQL语句,参数2——处理器对象,参数3——SQL语句的参数
		Student query = qr.query(sql, new BeanHandler<Student>(Student.class), 1);
		System.out.println(query);

	}
查询所有记录
BeanListHandler	将SQL语句的结果映射封装为List集合
		String sql = "select * from student ";
		//参数1——SQL语句,参数2——处理器对象
		List<Student> query = qr.query(sql, new BeanListHandler<Student>(Student.class));
		for (Student student : query) {
			System.out.println(student);
		}
插入语句
String sql = "insert into student values(null,?,?)";
int update = qr.update(sql, "阿大","28");//返回影响记录的行数
修改语句
String sql = "update student set name = ? where id = ?";
int update = qr.update(sql, "阿二",1);//返回影响记录的行数
删除语句
String sql = "delete from student where id = ?";
int update = qr.update(sql, 2);
自定义处理器需要实现ResultSetHandler接口
public class MyHandler implements ResultSetHandler<List<User>>{
 
   @Override
   public List<User> handle(ResultSet rs) throws SQLException {
      // 封装数据,数据从返回的结果集对象Resultset中获取
      List<student> list = new ArrayList<student>();
       while(rs.next()){
         student stu = new student();
         stu.setId(rs.getInt( "id"));
         stu.setName(rs.getString( "name"));
         stu.setAge(rs.getInt( "age"));
 
         list.add(stu);
      }
       return list;
   }
 
}
调用自定义处理器
String sql = "select * from student";
List<student> list = qr.query(sql, new MyHandler());
for (Student student : list) {
	System.out.println(student);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值