JDBC编程笔记整理1

JDBC编程
查询返回的是查询的结果集,修改返回的修改的行数
两个常用API:ODBC和JDBC
ODBC(Open DataBase Connectivity):开放式数据库连接,由Microsoft公司提供
JDBC(Java DataBase Connectivity):Java数据库连接,
JDBC是一种规范,
JDBC访问数据库过程
相关接口和类的作用:
Connection 此接口表示与数据的连接
PreparedStatement 此接口用于执行预编译的 SQL 语句
ResultSet 此接口表示了查询出来的数据库数据结果集
Statement 此接口用于执行 SQL 语句并将数据检索到 ResultSet 中
DriverManager 此类用于加载和卸载各种驱动程序并建立与数据库的连接
ResultSetMetaData 可用于获取关于ResultSet对象中列的类型和属性信息的对象

JDBC数据库访问过程:

  1. 注册和加载数据库驱动程序
  2. 通过Connection建立数据连接
  3. 通过createStatement()方法获取Statement对象
  4. 构造SQL语句
  5. 执行SQL语句
  6. 关闭相关资源

连接数据库的工具类:

package cn.goktech.utils;

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

/**
 * 连接数据库的工具类
 * @author asus
 *
 */
public class DBUtil {
	//创建连接对象,全部用静态,方便用类名调用
	private static Connection conn;  //使用static原因:如果不是连接池,一次最好建一个连接,
	private Statement state;
	private ResultSet rs;//结果集
	public static Connection getConnection() throws SQLException{
		try {
			Class.forName("com.mysql.jdbc.Driver");//Class是反射中常见类,com.mysql.jdbc.Driver是全类名
			//通过全类名把该类加载到内存
			/*
			 * url:连接数据库的字符串,-->用于表示协议:连接数据库:/连接数据库/用户:端口/数据库
			 * user:"root" 数据库的用户
			 * password:"123456" 数据库的密码
			 */
			conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test1806?characterEncoding=utf-8", "root", "123456");
			return conn;
			
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return conn;
		
	}
	/*
	 * 关闭数据库连接
	 */
	public static void closeConn(Statement state,ResultSet rs,PreparedStatement patmt){
		try{
				
				if(rs!=null){
					rs.close();
				}
				if(patmt!=null){
					patmt.close();
				}
				if(state!=null){
						state.close();
				}
				
				if(conn!=null){
					conn.close();
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			

	
	public static void main(String[] args) throws SQLException {
			
			Connection conn = getConnection();
			System.out.println(conn);
			
		}
	
}

创建一个Student类的JavaBean:

package cn.goktech.select;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import cn.goktech.entity.Student;
import cn.goktech.utils.DBUtil;
/**
 * 操作数据库的类
 * @author asus
 *Dao  持久层
 */
public class StudentDao {
	private Connection conn;
	private Statement state;
	private PreparedStatement patmt;
	private ResultSet rs;//结果集
	
	/**
	 * 返回数据库Student中的所有数据
	 * @return
	 * @throws SQLException 
	 */
	public List<Student> selectAll()  {
		List<Student> list = null;
		try {
			//准备容器(装Student)
			
			 list = new ArrayList<>();
			//1.获取数据库连接
			 conn = DBUtil.getConnection();
			
			//2.创建SQL语句
			String sql = "select * from student";
			
			//3.创建编译器
			 state = conn.createStatement();
			//4.执行SQL语句
			rs = state.executeQuery(sql);
			//5.处理结果集
			while(rs.next()){//next()  原因:因为是从0开始,0那里是没有数据的,必须next(),即1的地方才有数据
				Student stemp = new Student();
				stemp.setId(rs.getInt("id"));
				stemp.setName(rs.getString(2));

				list.add(stemp);
			}

			return list;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			
			DBUtil.closeConn(state,rs,patmt);
		}
		return null;
	}
	
	public Student selectById(int id)  {
		
		try {
			
			//1.获取数据库连接
			 conn = DBUtil.getConnection();
			
			//2.创建SQL语句
			String sql = "select * from student where id=?";
			
			//3.创建预编译器
			patmt = conn.prepareStatement(sql);
			patmt.setInt(1, id);
			//4.执行SQL语句
			rs = patmt.executeQuery();
			//5.处理结果集
			Student stemp = new Student();
			if(rs.next()){//next()  原因:因为是从0开始,0那里是没有数据的,必须next(),即1的地方才有数据
				stemp.setId(rs.getInt("id"));
				stemp.setName(rs.getString("name"));
				stemp.setCity(rs.getString("city"));
				stemp.setAge(rs.getInt("age"));
				System.out.println("-------------");
//				System.out.println(rs.getInt("id"));
//				System.out.println(rs.getString("name"));
					
			}
			else {
				return null;
			}
			return stemp;
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			
			DBUtil.closeConn(state,rs,patmt);
		}
		return null;
	}
	/**
	 * 通过id更新name
	 * 
	 * @param id
	 * @param name
	 * @return
	 * 事务:
	 * 原子性:事务的操作是不可分割的,每一步都属于事务的一部分,某一步出错,全部都不能执行
	 * 隔离性:多事务存在时,决定事务的存储顺序
	 * 一致性:多事务在开始后,未结束前数据对外不可见的,保障了事务的并发性
	 * 持久性:事务对于数据的操作是永久的,就是存在数据库,也就是硬盘中
	 */
	public boolean updateNameById(int id,String name)  {
		List<Student> list = null;
		try {
			//准备容器(装Student)
			
			 list = new ArrayList<>();
			//1.获取数据库连接
			 conn = DBUtil.getConnection();
			//取消自动提交
			 conn.setAutoCommit(false);
			//2.创建SQL语句
			String sql = "update student set name=? where id=?";
			
			//3.创建预编译器
			patmt = conn.prepareStatement(sql);
			patmt.setString(1, name);
			patmt.setInt(2, id);
			//4.执行SQL语句
			int number =  patmt.executeUpdate();
			conn.commit();
			//5.处理结果集
			Student stemp = new Student();
			if(number!=0){//next()  原因:因为是从0开始,0那里是没有数据的,必须next(),即1的地方才有数据
				return true;
			}
			else {
				return false;
			}
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}finally{
			
			DBUtil.closeConn(state,rs,patmt);
		}
		return false;
		
	}
	
	public static void main(String[] args) {
		StudentDao studentDao = new StudentDao();
		List<Student> list = studentDao.selectAll();
		list.stream().forEach(System.out::println);//JDK8
//		list.stream().forEach(s->System.out.println(s));//入表达式,效果同上
		System.out.println("--------------------");
		Student s1 = studentDao.selectById(3);
		System.out.println(s1);
		System.out.println("-------------");
		System.out.println(studentDao.updateNameById(1, "xiaohong"));
		
	}

}

代码未执行前,查询数据库中的数据:
select * from student;
在这里插入图片描述
执行代码后,控制台输出内容:
在这里插入图片描述
在数据库中再执行
select * from student;
在这里插入图片描述
如果对数据库进行查询和修改相关操作为以下代码:

package cn.goktech.select;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import cn.goktech.entity.Student;
import cn.goktech.utils.DBUtil;
/**
 * 操作数据库的类
 * @author asus
 *Dao  持久层
 */
public class StudentDao {
	private Connection conn;
	private Statement state;
	private PreparedStatement patmt;
	private ResultSet rs;//结果集
	
	/**
	 * 返回数据库Student中的所有数据
	 * @return
	 * @throws SQLException 
	 */
	public List<Student> selectAll()  {
		List<Student> list = null;
		try {
			//准备容器(装Student)
			
			 list = new ArrayList<>();
			//1.获取数据库连接
			 conn = DBUtil.getConnection();
			
			//2.创建SQL语句
			String sql = "select * from student";
			
			//3.创建编译器
			 state = conn.createStatement();
			//4.执行SQL语句
			rs = state.executeQuery(sql);
			//5.处理结果集
			while(rs.next()){//next()  原因:因为是从0开始,0那里是没有数据的,必须next(),即1的地方才有数据
				Student stemp = new Student();
				stemp.setId(rs.getInt("id"));
				stemp.setName(rs.getString(2));//  2 表示第二列,即name字段
				stemp.setCity(rs.getString("city"));
				stemp.setAge(rs.getInt("age"));

				list.add(stemp);
			}

			return list;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			
			DBUtil.closeConn(state,rs,patmt);
		}
		return null;
	}
	
	public Student selectById(int id)  {
		
		try {
			
			//1.获取数据库连接
			 conn = DBUtil.getConnection();
			
			//2.创建SQL语句
			String sql = "select * from student where id=?";
			
			//3.创建预编译器
			patmt = conn.prepareStatement(sql);
			patmt.setInt(1, id);
			//4.执行SQL语句
			rs = patmt.executeQuery();
			//5.处理结果集
			Student stemp = new Student();
			if(rs.next()){//next()  原因:因为是从0开始,0那里是没有数据的,必须next(),即1的地方才有数据
				stemp.setId(rs.getInt("id"));
				stemp.setName(rs.getString("name"));
				stemp.setCity(rs.getString("city"));
				stemp.setAge(rs.getInt("age"));
				System.out.println("-------------");
//				System.out.println(rs.getInt("id"));
//				System.out.println(rs.getString("name"));
					
			}
			else {
				return null;
			}
			return stemp;
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			
			DBUtil.closeConn(state,rs,patmt);
		}
		return null;
	}
	/**
	 * 通过id更新name
	 * 
	 * @param id
	 * @param name
	 * @return
	 * 事务:
	 * 原子性:事务的操作是不可分割的,每一步都属于事务的一部分,某一步出错,全部都不能执行
	 * 隔离性:多事务存在时,决定事务的存储顺序
	 * 一致性:多事务在开始后,未结束前数据对外不可见的,保障了事务的并发性
	 * 持久性:事务对于数据的操作是永久的,就是存在数据库,也就是硬盘中
	 */
	public boolean updateNameById(int id,String name)  {
		List<Student> list = null;
		try {
			//准备容器(装Student)
			
			 list = new ArrayList<>();
			//1.获取数据库连接
			 conn = DBUtil.getConnection();
			//取消自动提交
			 conn.setAutoCommit(false);
			//2.创建SQL语句
			String sql = "update student set name=? where id=?";
			
			//3.创建预编译器
			patmt = conn.prepareStatement(sql);
			patmt.setString(1, name);
			patmt.setInt(2, id);
			//4.执行SQL语句
			int number =  patmt.executeUpdate();
			conn.commit();
			//5.处理结果集
			Student stemp = new Student();
			if(number!=0){//next()  原因:因为是从0开始,0那里是没有数据的,必须next(),即1的地方才有数据
				return true;
			}
			else {
				return false;
			}
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}finally{
			
			DBUtil.closeConn(state,rs,patmt);
		}
		return false;
		
	}
	
	public static void main(String[] args) {
		StudentDao studentDao = new StudentDao();
		List<Student> list = studentDao.selectAll();
		list.stream().forEach(System.out::println);//JDK8
//		list.stream().forEach(s->System.out.println(s));//入表达式,效果同上
		System.out.println("--------------------");
		Student s1 = studentDao.selectById(3);
		System.out.println(s1);
		System.out.println("-------------");
		System.out.println(studentDao.updateNameById(1, "xiaohong"));
		
	}

}

在这里插入图片描述
PreparedStatement和Statement区别

  1. PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
  2. PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement
    对象的 setXXX() 方法来设置这些参数.
  3. 使用PreparedStatement可以防范SQL注入
  4. 使用PreparedStatement效率更高,速度更快
发布了81 篇原创文章 · 获赞 25 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43090158/article/details/95720562