Jdbc基础知识

Jdbc基础知识

一:原生jdbc基础

1.jdbc的本质

	本质就是sun公司提供的一套接口规范:接口的子实现类

2.jdbc的相关核心类

1).DriverManager类:1)管理和注册数据库驱动
				2)获取数据库连接对象
		成员方法
				public static void registerDriver(Driver driver):注册驱动
				public static Connection getConnection(	
										String url,
       									String user,
                                       String password):获取数据库的连接对象
                                通过创建系统资源发送到数据库的一种url请求 
                参数1:
                	url:统一资源定位符
                	协议://域名或者ip地址:端口号/链接具体地址
                	jdbc:mysql://localhost:3306/数据库名称
                 参数2:用户名:root用户
                 参数3:密码

2).Connection接口:一个连接对象,可用于创建Statement和PreparedStatement
	成员方法
			有关事务管理相关的方法
			void setAutoCommit(boolean autoCommit):设置数据库的提交方式 :
					参数为true:表示自动提交
					参数为false:表示禁用自动提交
			void rollback():事务的回滚
			void commit():事务的提交
			
			与数据库执行对象相关方法
				Statement createStatement():创建Statement对象,将指定sql发送到数据库中
				PreparedStatement prepareStatement(String sql):将

3).Statement接口:一个sql语句对象,用于将sql语句发送给数据库服务器
	成员方法
			int executeUpdate(String sql) : 通过Statement将静态sql语句发送到数据库中进行操作
							执行增删该
			
			ResultSet executeQuery(String sql):执行查询语句select...

4).PreparedStatement接口:预编译处理对象,一个sql语句对象,是Statement的子接口
	int executeUpdate():对预编译对象中sql语句直接操作!
5).ResultSet接口:用于封装数据库查询的结果集,返回给客户端的java程序
	成员方法
					boolean next():判断下一行是否存在有效数据!
					
					XXX getXXX(int columnIndex):根据列的索引值获取表中结果数据:索引值1开始
						如果是第一列,则为1
						....第二列,则为2
					XXX getXXX(String columnLabel):根据列的名称获取

3.环境搭建

1)在项目下新建 lib 文件夹,用于存放 jar 文件。
2)将 mysql 驱动mysql-connector-java-5.1.X复制到项目的 lib 文件夹中。
3)选中 lib 文件夹右键 Add as Libraay,点击 OK。

4.jdbc操作数据库步骤

1)导包:mysql驱动jar包--mysql-connector-java-5.1.37-bin.jar
2)注册驱动:
		Class.forName("com.mysql.jdbc.Driver");
3)获取数据库连接对象:
		Connection conn=DriverManager.getConnection(
	        "jdbc:mysql://localhost:3306/mydb_01",
	         "root",
	         "root"
		);
4)准备sql语句:
			String sql="update student set name="小九" where id =2";
5)通过数据库连接对象获取执行对象
		Statement stmt=conn.createStatement();
6)执行sql语句
		int count=stmt.executeUpdate(sql);
7)处理返回结果
		if(count>0){
		System.out.println("成功");
		}
8)释放资源(先开后关原则)
       statement.close();
       connection.colse();
		
代码案例:
publicclassJobsQuery{
	publicstaticvoidmain(String[]args){
		//1.加载驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2.获取数据库连接对象	
        Connection conn=DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/mydb_01","root","root\");
        //3.获取发送sql语句对象
        Statement st=conn.createStatement();
        //4.执行SQL语句并接收结果集
        ResultSet resultSet=statement.executeQuery("select* from t_jobs");
        //5处理结果集
        while(resultSet.next()){
        //5.1有数据,依据列名获取数据
        Stringjob_id=resultSet.getString("job_id");
      	Stringjob_title=resultSet.getString("job_title")
      	intmin_salary=resultSet.getInt("min_salary");
      	intmax_salary=resultSet.getInt("max_salary");
      System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);
      }
      //5.2有数据:根据列的编号获取数据
      	while(resultSet.next()){
      		Stringjob_id=resultSet.getString(1);
      		Stringjob_title=resultSet.getString(2);
      		intmin_salary=resultSet.getInt(3);
      		intmax_salary=resultSet.getInt(4);
      System.out.println(job_id+"\t"+job_title+"\t"+min_salary+"\t"+max_salary);}
      //6.释放资源
      	rs.close();
      	st.close();
      	conn.close();
      }
     }
    }
   }

5.statement与PreparedStatement

 需求:
 	键盘录入用户名和密码,模拟用户登录操作
   后台---有一张user表:用户表
  如果键盘录入的用户名和密码和数据库中user表中用户名和密码一致,登录成功! 否则,"用户名或者密码错误" 存在问题:
  什么是 SQL 注入:
  		用户输入的数据中有 SQL 关键字或语法并且参与了 SQL 语句的编译,导致 SQL 语句编译后的条件含义为true,一直得到正确的结果。这种现象称为 SQL 注入。
 使用Statemet对象:存在严重问题:SQL注入: 不安全的行为
  select * from user where username = 'sdfsd' and password = 'a' or 'a' = 'a'
 用户名和密码完全不一致,依然可以登录成功!
 Statement对象:
  	1.弊端
 		1)执行效率差
		每一次发送sql语句之前,获取Statement 
 			executeUpdate(String sql)
			executeQuery(String sql)
 		2)存在安全漏洞:sql注入  存在字符串拼接导致的!
    2.解决: 为了提高执行效率以及防止sql注入
  sun公司提供了一个接口:PreparedStatement
		将参数化的sql语句先进行预编译(在PreparedStatement对象中 内存中)
		参数化的sql语句不存在硬编码的拼接!
	3.二者的区别:
	  执行对象
	    Statement:
	    	1)操作的静态sql语句 
	    	2)通过连接对象获取Statement
	     	3)Statement发送sql到数据库中,操作sql语句效率低,executeUpdate(String sql) executeQuery(String sql)
	     	4)存在字符串拼接,造成sql注入
		PreparedStatement:预编译对象
	         1)通过连接对象获取预编译对象的同时将参数化的sql发送数据库进行预编译!
	         2)相对Statement对象,执行效率高
	         3)能够有效防止sql注入	

1)PreparedStatemet实现用户登录,注册操作代码体现
public class StatementTest{
	public static void main(string[] args){
		//创建键盘录入对象
		Scanner sc=new Scanner(System.in);
		//提示并录入数据
		System.out.println("请输入用户名:");
		String username = sc.nextLine() ;
		System.out.println("请输入密码:");
		String password = sc.nextLine() ;
		//调用方法
		boolean flag=isLogin(username,password);
		if(flag){
			System.out.println("恭喜你,登录成功!");
		}
		else{
		System.out.println("登录失败,您的用户名或密码不正确");
		}
		
	}
	//登录页面实现方法
	private static boolean isLogin(String username,String password){
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		try{
			//获取数据库连接对象
			conn=JdbcUtils.getconnection();
			//准备SQL语句(通过用户名和密码查询用户---查询某一条件记录---如果有内容:存在)
			String sql="select *from user where username=? and password=?";
			//将参数化的sql语句发送数据库进行预编译
			stmt=conn.prepareStatement(sql);
			//给占位符赋值void setXXX(nt parameterIndex,实际参数)
			 //参数1:?是第几个占位符
			 //参数2:实际参数
			 stmt.setString(1,username);
			 stmt.setString(2,password);
			 //执行查询更新
			 rs=stmt.executQuery();
			 return rs.next();
		}catch (SQLException e) {
			e.printStackTrace();
		}finally {
			JdbcUtils.close(rs, stmt, conn);	
		}
		return false
	}	
}

6.PreparedStatement执行DML和DQL的基本操作是什么

1)注册驱动
2)获取数据库连接
3)准备参数化的sql
4)通过连接对象获取预编译对象
		连接对象.prepareStatement(String sql)---->PreparedStatement
5)参数赋值
			通过setXXX(占位符的索引值,实际参数) 对占位符号进行赋值
6)执行
			int execueteUpdate()
			ResultSet executeQuery()
查询的:还需要遍历结果集
				
				

二.针对原生jdbc进行工具类的封装

1.工具类的封装

1)封装步骤
静态代码块static{
		将jdbc.properties配置文件加载到属性集合类中Properties
		获取里面参数信息
			driverClass
			user
			url
			password
			注册驱动
			}	
封装获取连接对象的方法getConnection()
封装释放资源的方法close(ResultSet rs,Statement stmt,Connection conn) ;
		close(Statement stmt,Connection conn)
			

2).代码体现
public class JdbcUtils{
	//成员变量的位置
	public static String url = null ;
	public static String user = null ;
	public static String password = null ;
	//提供一个属性
	public static String driverClass = null	
	//提供一个静态代码块(随类的加载而加载)
	//在加载JdbcUtils类的时候,静态代码中的内容优先执行
	static {
		try {
			//创建一个属性集合类对象
			Properties prop = new Properties() ;	
			//将jdbc.properties的配置文件内容加载到prop属性集合中
			 InputStream inputStream =  JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties") ;
			 prop.load(inputStream); 
			 //通过prop的键获取值
			  url = prop.getProperty("url") ;
			  user = prop.getProperty("user") ;
			  password = prop.getProperty("password") ;
			  driverClass = prop.getProperty("driverClass") ;
			 //注册驱动
			  Class.forName(driverClass) ;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} 
	}
	//构造方法私有化
	private JdbcUtils() {}
	//静态功能
	//获取连接对象--封装
	public static Connection getConnection() {
		//需要通过驱动管理类获取 DriverManager
		//三个参数需要放在配置文件 xx.properites----将三个参数:jdbc.properties
		try {
			Connection conn  = DriverManager.getConnection(url, user, password);
			return conn ;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null ;
	}
	//关闭资源---封装
	//针对DQL语句进行操作:释放资源
	public static void close(ResultSet rs,Statement stmt,Connection conn) {
		if(rs!=null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(conn!=null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	//针对DDL/DML:增删改 释放资源
	public static void close(Statement stmt,Connection conn) {
		
		close(null, stmt, conn);
	}

}

2.jdbc.properties配置文件

url=jdbc:mysql://localhost
user=root
password=root
driverClass=com.mysql.jdbc.Driver

3.测试案例(原生jdbc工具类进行增删查改)

1)需求
1.创建一个部门表dept,提供部门编号,部门名称,部门位置,使用原生JDBC(封装成工具类的形式)对dept表进行操作该
		a)需要通过外置属性文件进行读取数据库 连接信息
	    b)分页展示dept表的数据信息,每页展示2条,并将数据封装到List<Dept>中(参数为每页条数和展示的页码)
		c)向dept表中插入50,"DEVELOPMENT","China"(参数为dept对象)
		d)删除dept表中50号部门的信息(参数为部门编号)
		e)通过部门编号查询部门
		f)查询全部
		7)查询总记录数
2.代码体现
public class DeptDaoImpl{
 //插入操作
 public static void addDept(Dept dept){
      Connecton conn=null;
      PrepareStatemet stmt=null;
      try{
      	conn=JdbcUtils.getConnection();
      	String sql="insret into dept (dept_id,dept_name,dept_loc) values (?,?,?)";
      	stmt=conn.prepareStatement(sql);
      	stmt.setInt(1,dept.dept_id);
      	stmt.setString(2,dept.dept_name);
      	stmt.setString(3,dept.dept_loc);
      	int count=stmt.executeUpdate();
      	if(count>0){
      	System.out.println("数据插入成功");
      	}
      }catch (SQLException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	  }finally {
	    JdbcUtils.close(conn, pstmt);
	   }
 }
 //删除操作
 public static void delete(int dept_id){
 	Connection conn=null;
 	PreparedStatement stmt=null;
 	try{
 		conn=JdbcUtils.getConnection();
 		String sql="delete from dept where dept_id =?";
 		stmt=conn.prepareStatement(sql);
 		stmt.setInt(1,dept_id);
 		int count=stmt.executeUpdate();
 		if(count>0){
 		System.out.println(数据删除成功!);
 		}
 	}
 }
 //通过id查询
 public static Dept getDept(int deptid){
	 Connection conn=null;
 	PreparedStatement stmt=null;
 	ResultSet rs=null;
 	Dept dept=new Dept;
 	try{
 		conn=JdbcUtils.getConnection();
 		String sql="select *from dept where dept_id=?";
 		stmt=conn.prepareStatement(sql);
 		stmt.setInt(1,deptid);
 		rs=stmt.executeQuery();
 		while(rs.next()){
 		 int id=rs.getInt("id");
 		 int dept_id=rs.getInt("dept_id");
 		 String dept_name=rs.getString("dept_name");
 		 String dept_loc=rs.getString("dept_loc");
 		 d.setDept_id(dept_id);
 		 d.setId(id);
 		 d.setDept_name(dept_name);
 		 d.setDept_loc(dept_loc);
 		}
 		return d;
 	}catch (SQLException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}finally{
	    JdbcUtils.close(rs, conn, pstmt);
	}
	return null;}
 }
  //分页展示dept表的数据信息,每页展示2条,并将数据封装到List<Dept>中
  public static void findAll(int tiao,int ye){
  Connection conn=null;
	ResultSet rs=null;
	PreparedStatement pstmt=null;
	Dept dept=null;
	ArrayList<Dept> list=new ArrayList<Dept>();
	
	try {
	    conn=JdbcUtils.getConnection();
	    String sql="select *from dept limit ?,?";
	    pstmt=conn.prepareStatement(sql);
	    int hang=(ye-1)*tiao;
		pstmt.setInt(1, hang);
		pstmt.setInt(2, ye);
		rs=pstmt.executeQuery();
		while(rs.next()) {
			dept=new Dept();
			//获取数据
			int id=rs.getInt("id");
			int dept_id=rs.getInt("dept_id");
			String dept_name=rs.getString("dept_name");
			String dept_loc=rs.getString("dept_loc");
			//将数据封装到Dept对象中
			dept.setDept_id(dept_id);
			dept.setId(id);
			dept.setDept_name(dept_name);
			dept.setDept_loc(dept_loc);
		
			list.add(dept);
			
		}
		if(list!=null) {
		    for(Dept d:list) {
			System.out.println(d);
		    }
		}
	} catch (SQLException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}finally {
	    JdbcUtils.close(rs, conn, pstmt);
	}
  }
  //输出记录总数
  public long getCount(){
  	 Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs1=null;
		List<User> list=null;
		Dept dept=null;
		try{
		conn=JdbcUtils.getConnection();
		String sql="select *from dept ";
		stmt=conn.prepareStstement(sql);
		rs=stmt.executeQuery();
		while(rs.next()){
				dept=new Dept();
			//获取数据
			int id=rs.getInt("id");
			int dept_id=rs.getInt("dept_id");
			String dept_name=rs.getString("dept_name");
			String dept_loc=rs.getString("dept_loc");
			//将数据封装到Dept对象中
			dept.setDept_id(dept_id);
			dept.setId(id);
			dept.setDept_name(dept_name);
			dept.setDept_loc(dept_loc);
		
			list.add(dept);
			}return list.size;
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JdbcUtils.close(rs1, stmt, conn);
		}
		return 0
		
		
		}
  }

}

三:连接池

连接池 :
 	连接对象可以重复利用(固定的 /可重用的)-----使用完毕之后会再次归还到连接池中
自动参与连接 
 sun提供了接口 java.sql.DataSource:物理数据源的链接----代替了DriverManager工具(jdbc的一组服务)
  成员方法
  		Connection getConnection();
  驱动类的厂商提供: 
 			c3p0核心jar包  源码包		--- 日志记录
 			druid核心jar包 源码包
  			dbcp核心jar包...
  

(一).c3p0连接池

 c3p0连接池----相关的jar包
1)导入jar包
 		c3p0-0.9.5.2.jar  -核心jar包
 		mchange-commons-java-0.2.12.jar  c3p0的依赖包
2)需要将c3p0核心配置文件存储在src目录下  自动读取
 两种方式
  	c3p0.properties
  	c3p0-config.xml ----- spring,springmvc,mybatis主流框架xml文件配置方式
 3)配置文件中提了一些
    基本参数
 		driverClass:数据库驱动实现
		jdbcUrl 连接特定的数据库
		user用户名
		password 密码
	
    连接池的参数信息
      	initialPoolSize :初始化连接数量
     	maxPoolSize:最大连接数量
     	checkoutTimeout:超时时间 单位为毫秒  如果超过最大连接数量,在指定时间连接不上,就会出现问题了

(二).druid连接池

1.druid相关知识
druid连接池----相关的jar包
 1) 导入核心jar包  
	druid-1.0.9.jar		--- DruidDataSource
 2)在src目录执行核心配置文件
   	jdbc.properites (名称可以随便起)
   	有一些基本参数信息
   	连接池的信息  
   	
druid里面内置的属性名字
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb_02
username=root
password=123456
连接池的默认配置信息
initialSize=5  初始化连接数量5
maxActive=10   最大激活数量10个
maxWait=3000    最大的等待时间
3)获取连接对象呢?
使DruidDataSourceFactory:德鲁伊的物理数据源的工厂类
静态方法

2.Druid 连接池配置文件(druid.propertise)
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb_05
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
3.Druid工具类
封装工具类
 	1)使用连接池获取连接对象 ----Druid连接池
	DruidDataSourceFactory.createDataSource(Properties prop)--->javax.sql.DataSource		2)封装获取连接的方法
    mygetConnection()-----DataSource对象可以调用getConnection()
 	3)释放资源
 
public class MyJdbcUtils {
	//成员位置声明
	private static DruidDataSource ds ; //直接使用具体的子实现类:DruidDataSource
	private MyJdbcUtils() {}
	static {
		try {
			//创建一个属性集合类对象
			Properties prop = new Properties() ;
			//读取druid.properties 核心配置文件
			InputStream inputStream = MyJdbcUtils.class.
					getClassLoader().getResourceAsStream("druid.properties") ;
			//加载到prop
			prop.load(inputStream);
			//通过Druid连接池提供 的工厂类创建物理数据源DataSource
			ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(prop) ;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
	//获取数据库连接
	public static Connection getConnection() {
		Connection conn = null ;
		try {
			conn = ds.getConnection() ;
			return conn ;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null ;
	}	
	//获取DataSource的方法
	public static DataSource getDataSource() {
		return ds; 
	}
	//释放资源的方法
	public static void close(ResultSet rs,PreparedStatement stmt,Connection conn) {
		if(rs!=null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(stmt!=null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}	
		if(conn!=null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void close(PreparedStatement stmt,Connection conn) {
		close(null, stmt, conn);
	}
	
	//开启事务
	
	/*
	public static void startTransaction(Connection conn) {
		if(conn!=null) {
			try {
				conn.setAutoCommit(false);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	*/
	
4.Druid包含的接口和类
ResultSetHandler接口:转换类型接口
	BeanHandler类:实现类,把一条记录转换成对象
	BeanListHandler类:实现类,把多条记录转换成List集合。
	ScalarHandler类:实现类,适合获取一行一列的数据。
QueryRunner:执行sql语句的类增、删、改:update();查询:query();
5.Druid常量池工具实现数据库的增删查改
public class UserDaoImpl{
//添加数据
	public  void addUser(User user) throws SQLException{
		//创建执行对象
		QueryRunner qr=new QueryRunner(MyJdbcUtils.getDataSource());
		//准备sql语句:必须是参数化sql
		String sql="insert into user() values(?,?,?,?)"
		//执行更新
		int count=qr.update(sql,
		     user.getName(),
		     user.getGender(),
		     user.getAddress(),
		     user.getPhone());
		 if(count >0){
		 System.out.println("数据插入成功");
		 }
	}
	//删除数据
	public  void deleteUser(int id){
		try{
		QueryRunner qr=new QueryRunner(MyJdbcUtils.getDataSource());
		String sql="delete from user where id = ?";
		int count = qr.update(sql,id);
		if(count>0){
			System.out.println("数据删除成功");
		}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//查询单个数据
	public User getUserById(intid){
		try{
		QueryRunner qr=new QueryRunner(MyJdbcUtils.getDataSource());
		String sql="select * from user where id id=?";
		User user=null;
		user=qr.query(sql,new BeanHandler<User>(User.class),id);
		System.out.println(user);
		retirn user;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	//查询所有数据
	public List<User> findAll(){
		List<User> list=new arrayList<User>();
		try{
		QueryRunner qr=new QueryRunner(MyJdbcUtils.getDataSource());
		String sql="select * from";
		list=qr.query(sql,new BeandListHandler<User>(User.class));
			for(User user:list){
				System.out.println(list);
				}
			return list;
		}catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	//查询记录总数
	public long count(){
	 List<User> list=null;
	 try{
	 QueryRunner qr=new QueryRunner(MyJdbcUtils.getDataSource());
	 String sql="select count(id) from user";
	 long count=qr.query(sql,new ScalarHandleder<User>());
	 return count;
	 }catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值