JDBC全集,详细,含JDBC类和接口,工作原理,连接数据库案例,SQL注入,JDBC三层架构,连接池技术(C3P0,druid)

JDBC是什么

  • JDBC(Java Database Connectivity)是JAVA访问数据库的解决方案
  • JDBC定义了一套标准接口,即访问数据库的通用API,实现不同的数据库厂商根据各自数据库的特点去实现这些接口
  • JDBC希望用相同的方式访问不同的数据库,让具体的数据库操作与数据库厂商实现无关,从而在不同数据库之间轻易的进行切换(跨平台性

JDBC相关类和接口

  • 驱动类:DriverManager
  • 连接接口:Connection
  • 语句对象接口:Statement
  • 结果集接口:ResultSet

JDBC工作原理

在这里插入图片描述

下载驱动

  • 下载对应的数据库的驱动(数据库官网)

    ​ mysql-connector-java-5.0.4-bin.jar

  • 将驱动类加载到项目中(jar包导入到项目中)

    ​ Build Path 构建路径

加载驱动(1)

// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
  • 加载驱动类
  • 通过Class.forName( )方法(反射)完成驱动类的注册

Connection接口(2)

  • 根据URL连接参数找到与之匹配的Driver对象,调用其方法获取连接
Connection conn =DriverManager.getConnection(url, user, password);
// Connection类名 conn对象名 url:数据库地址 user:数据库用户 password:密码
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
  • url:“jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT”
    1. dbc:mysql://:连接字符串
    2. localhost:3306:数据库地址及端口号
    3. myschool:库名
    4. serverTimezone:时区设置

注意::Connection只是接口!真正的实现是数据库厂商提供的驱动包完成的

Statement接口(3)

Statement用于执行SQL语句

注意:不用的SQL语句要用不同的方法来执行

Statement执行DML

DML:insert、update、delete,返回值是被影响的行数,用int接受

// 创建sql语句
String sql = "insert into 表名 values(……)";

// 创建执行sql语句的对象
Statement statem = conn.createStatement();

// 执行sql语句
int res = statem.executeUpdate(sql);

Statement执行DQL

DQL:select,返回值是结果集,用ResultSet接收

// 创建sql语句
String sql = "select * from 表名";

// 创建执行sql语句的对象
Statement statem = conn.createStatement();

// 执行sql语句
ResultSet res =  statem.executeQuery(sql);

ResultSet接口(4)

查询结果存放在ResultSet对象的一系列行中

  • ResultSet对象的最初位置在行首
  • ResultSet.next()方法用来在行间移动
  • ResultSet.getXXX()方法用来取得字段的内容
while(res.next()) {
	int sid = res.getInt("sid");
	String name = res.getString("sname");
	String bir = res.getString("birthday");
	String ssex = res.getString("ssex");
	int classid = res.getInt("classid");
	System.out.println(sid+name+bir+ssex+classid);
}

关闭并释放资源(5)

数据库操作执行完毕以后要释放相关资源

  • Connection
  • Statement
  • ResultSet
re.close();
statem.close();
conn.close();

注意:释放资源顺序,先得到的资源后释放

案例

  • insert

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class InsertDemo1 {
    	public static void main(String[] args) throws ClassNotFoundException, SQLException {
    		// 加载驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    		
    		// 2.获取连接
    		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
    		
    		// 3.0 创建sql语句
    		String sql = "insert into student(sname,birthday,ssex,classid) values ('曹贼','2000-1-1','男',1)";
    		// 3.1 创建执行sql语句对象
    	 	Statement statem = conn.createStatement();
    		// 3.2 执行sql语句
    	 	int ret = statem.executeUpdate(sql);
            
    	 	// 业务逻辑
    	 	if(ret >0) {
    	 		System.out.println("添加成功");
    	 	}else {
    	 		System.out.println("添加失败");
    	 	}
    	 	
    	 	// 4.释放资源
    	 	statem.close();
    	 	conn.close();
    	}
    }
    
  • update

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    
    public class UpdateDemo01 {
    	public static void main(String[] args) throws ClassNotFoundException, SQLException {
    		Scanner input = new Scanner(System.in);
    		// 1.加载驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    		
    		// 2.获取连接
    		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT","root", "123456");
    		
    		// 3.创建sql语句
    		System.out.println("请输入修改学生的编号");
    		int sid = input.nextInt();
    		System.out.println("请输入学生新的名字");
    		String sname = input.next();
    		System.out.println("请输入学生的新生日(yyyy-MMydd格式)");
    		String bir = input.next();
    		System.out.println("请输入学生的性别");
    		String ssex = input.next();
    		System.out.println("请输入学生的班级号");
    		int classid = input.nextInt();
    		
    		String sql = "update student set sname='"+sname+"',birthday = '"+bir+"',ssex='"+ssex+"',classid='"+classid+"' where sid = "+ sid;
    		
    		// 获取执行对象
    		Statement statem = conn.createStatement();
    		
    		int ret = statem.executeUpdate(sql);
    		
    		if(ret>0) {
    			System.out.println("修改成功");
    		}else {
    			System.out.println("修改失败");
    		}
    		
    		// 释放资源
    		statem.close();
    		conn.close();
    	}
    }
    
  • delete

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.Scanner;
    
    public class DeleteDemo1 {
    	public static void main(String[] args) throws ClassNotFoundException, SQLException {
    		Scanner input = new Scanner(System.in);
    		// 加载驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    					
    		// 2.获取连接
    		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
    					
    		// 3.0 创建sql语句
    		System.out.println("请输出要删除的学生编号");
    		int sid = input.nextInt();
    		String sql = "delete from student where sid=" + sid;
    		// 3.1 创建执行sql语句对象
    		Statement statem = conn.createStatement();
    		// 3.2 执行sql语句
    		int ret = statem.executeUpdate(sql);
    				 	
    		// System.out.println(ret);
    				 	
    		// 业务逻辑
    		if(ret >0) {
    				System.out.println("删除成功");
    		}else {
    				System.out.println("删除失败");
    		}
    				 	
    		// 4.释放资源
    		statem.close();
    		conn.close();
    	}
    }
    
  • select

    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.text.SimpleDateFormat;
    
    public class SelectTest {
    
    	public static void main(String[] args) throws ClassNotFoundException, SQLException {
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		// 1. 加载驱动
    		Class.forName("com.mysql.cj.jdbc.Driver");
    		// 2. 获取连接
    		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
    		// 3. 创建sql语句
    		String sql = "select sname,birthday,ssex,sid,classid from student";
    		// 3.1 执行对象
    		Statement statm = conn.createStatement();
    		// 3.2 执行
    		ResultSet rs = statm.executeQuery(sql);
    		while(rs.next()){
    			// 解析结果集
                // 字段下标的方式(不推荐)
    //			int sid = rs.getInt(1);
    //			String sname = rs.getString(2);
    //			String bir = rs.getString(3);
    //			Date date = rs.getDate(3);
    //			String ssex = rs.getString(4);
    //			int classid = rs.getInt(5);
    			
    			// 字段名的方式解析结果集
    			int sid = rs.getInt("sid");
    			int classid = rs.getInt("classid");
    			String sname = rs.getString("sname");
    			String ssex = rs.getString("ssex");
    			Date bir = rs.getDate("birthday");
    			System.out.println(sid+sname+bir+ssex+classid);
    		}
    
    		// 4. 释放资源
    		rs.close();
    		statm.close();
    		conn.close();
    	}
    }
    

SQL注入

现有需求:做一个登录业

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

public class LoginTest {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		
		Scanner input = new Scanner(System.in);
		
		// 1. 加载驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		
		// 2. 获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
		
		System.out.println("请输入账号");
		String username = input.nextLine();
		System.out.println("请输入密码");
		String userpwd = input.nextLine();

		// 3. 登录  -- 将sql语句中的传参的地方用 ? 占位
		String sql = "select * from login where lusername='"+username+"' + and luserpwd='"+userpwd+"'";
		
		// 3.1 执行对象
		Statement statm = conn.createStatement(); 
		// 3.2 执行
		// ' or 1=1 --   sql注入
		ResultSet rs = statm.executeQuery(sql);
		if(rs.next()) {
			int lid = rs.getInt("lid");
			String lusername = rs.getString("lusername");
			String luserpwd = rs.getString("luserpwd");
			String luname = rs.getString("luname");
			String lusex = rs.getString("lusex");
			String laddress = rs.getString("laddress");
			System.out.println(lid+lusername+luserpwd+luname+lusex+laddress);
			System.out.println("登录成功");
		}else {
			System.out.println("账号密码错误");
		}
		// 释放资源
		rs.close();
//		statm.close();
		prestatm.close();
		conn.close();
	}
}

当输入正常的账号密码时,业务逻辑正确,但当账号输入

' or 1=1 --

此时,业务逻辑出现问题,原因是SQL语句的拼接,原本的SQL语句是

select * from login where lusername='……' and luserpwd='……'

但当账号输入特殊符号语句时,SQL语句变成

select * from login where lusername='' or 1=1 -- and luserpwd='……'

此账号把原本的SQL语句条件更改了,变成了全查,导致账号密码不正确时业务逻辑也是登陆成功,解决方法是在特殊符号添加转义符,但是实现起来非常困难,所以有新的方法如下

  • 避免SQL注入问题不用Statement,使用Preparement

使用Preparement对象,创建SQL语句写参数时,需要用占位符?占位参数,再调用Preparement对象的setObject(parameterIndex, x)方法,把参数传给SQL语句

  • parameterIndex:SQL语句中参数的位置,所有和SQL有关的索引都从1开始
  • x:传入参数的名
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

public class LoginDemo1 {
	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		Scanner input = new Scanner(System.in);
		// 1.加载驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		
		// 2.获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
		
		// 用户输入数据
		System.out.println("请输入账号:");
		String username = input.nextLine();
		System.out.println("请输入密码");
		String userpwd = input.nextLine();
		
		// 3.创建SQL语句
		String sql = "select * from login where lusername = ? and luserpwd = ?";
		
		// 3.1 创建执行SQL语句的Preparement对象
		 PreparedStatement prestatem = conn.prepareStatement(sql);
		 
		 // 3.2 传参
		 prestatem.setObject(1,username);
		 prestatem.setObject(2, userpwd);
		
		 // 3.3 执行SQL语句
		 ResultSet res  = prestatem.executeQuery();
		 
		 if(res.next()) {
			 String lusername = res.getString("lusername");
			 String luserupwd = res.getString("luserpwd");
			 String luname = res.getString("luname");
			 String lusex = res.getString("lusex");
			 String laddress = res.getString("laddress");
			 System.out.println(lusername+luserupwd+luname+lusex+laddress);
			 System.out.println("登录成功");
		 }else{
			 System.out.println("账号或密码错误");
		 }
		 
		 // 释放资源
		 prestatem.close();
		 conn.close();
		 input.close();
	}
}

注意:Statement存在SQL注入的问题,已成为过去时,弃用,都用Preparement

JDBC三层架构

在这里插入图片描述

  • DAO层

    数据访问层,主要对数据库进行增删改查

  • service层

    业务逻辑层,主要做业务逻辑

  • view层

    视图层,主要与用户进行交互

  • JavaBean类

    实体类,封装数据,数据传输的负载

注:数据来源于用户,最终也要反馈给用户

  • 案例

  1. 包结构

    在这里插入图片描述

    • com.ape.bean:实体类包
    • com.ape.dao:dao层包,dao层接口
    • com.ape.dao.impl:com.ape.dao包下的包,实现dao接口的类
    • com.ape.service:service层包,service层接口
    • com.ape.service.impl:com.ape.service包下的包,实现service接口的类
    • com.ape.view:view层包,view层接口
    • com.ape.view.impl:com.ape.view包下的包,实现view接口的类
    • com.ape.test:测试类
  2. 代码

    • com.ape.bean

      package com.ape.bean;
      
      import java.util.Date;
      
      public class Student {
      	private int sid;
      	private String sname;
      	private Date birthday;
      	private String ssex;
      	private int classid;
      	
      	// 无参构造方法
      	public Student() {
      		super();
      	}
      	
      	// 全参构造方法
      	public Student(int sid, String sname, Date birthday, String ssex, int classid) {
      		super();
      		this.sid = sid;
      		this.sname = sname;
      		this.birthday = birthday;
      		this.ssex = ssex;
      		this.classid = classid;
      	}
      
      	// 重写toString方法
      	@Override
      	public String toString() {
      		return "Student [sid=" + sid + ", sname=" + sname + ", birthday=" + birthday + ", ssex=" + ssex + ", classid="
      				+ classid + "]";
      	}
      
      	public int getSid() {
      		return sid;
      	}
      	public void setSid(int sid) {
      		this.sid = sid;
      	}
      	public String getSname() {
      		return sname;
      	}
      	public void setSname(String sname) {
      		this.sname = sname;
      	}
      	public Date getBirthday() {
      		return birthday;
      	}
      	public void setBirthday(Date birthday) {
      		this.birthday = birthday;
      	}
      	public String getSsex() {
      		return ssex;
      	}
      	public void setSsex(String ssex) {
      		this.ssex = ssex;
      	}
      	public int getClassid() {
      		return classid;
      	}
      	public void setClassid(int classid) {
      		this.classid = classid;
      	}
      }
      
    • com.ape.dao

      package com.ape.dao;
      
      import java.util.List;
      
      import com.ape.bean.Student;
      
      public interface studentDao {
      	// 新增
      	public int addStudent(Student s);
      	
      	// 更新
      	public int updateStudent(Student s);
      	
      	// 删除
      	public int deleteStudent(Student s);
      	
      	// 查看
      	public Student findStudentBySid(int sid);
      	public List<Student> findAllStudent();
      }
      
    • com.ape.dao.impl

      package com.ape.dao.impl;
      
      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.ape.bean.Student;
      import com.ape.dao.studentDao;
      import com.mysql.cj.protocol.Resultset;
      import com.mysql.cj.xdevapi.Result;
      
      public class studentDaoImpl implements studentDao{
      
      	@Override
      	public int addStudent(Student s) {
      		int res =0;
      		Connection conn = null;
      		PreparedStatement prepstatem = null;
      		
      		try {
      			// 加载驱动
      			Class.forName("com.mysql.cj.jdbc.Driver");
      			// 获取连接
      			conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
      			
      			// 创建sql语句
      			String sql = "insert into student(sname,birthday,ssex,classid) values(?,?,?,?)";
      			
      			// 创建执行sql语句的对象
      			
      			prepstatem = conn.prepareStatement(sql);
      			
      			prepstatem.setObject(1, s.getSname());
      			prepstatem.setObject(2, s.getBirthday());
      			prepstatem.setObject(3, s.getSsex());
      			prepstatem.setObject(4, s.getClassid());
      			
      			res = prepstatem.executeUpdate();
      			
      		} catch (ClassNotFoundException e) {
      			e.printStackTrace();
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}finally {
      			if(prepstatem != null) {
      				try {
      					prepstatem.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			if(conn !=null) {
      				try {
      					conn.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      		}
      		return res;
      	}
      
      	// 修改
      	@Override
      	public int updateStudent(Student s) {
      		// TODO Auto-generated method stub
      		return 0;
      	}
      
      	// 删除
      	@Override
      	public int deleteStudent(Student s) {
      		// TODO Auto-generated method stub
      		return 0;
      	}
      
      	// 通过sid查找学生
      	@Override
      	public Student findStudentBySid(int sid) {
      		Student s = null;
      		Connection conn = null;
      		PreparedStatement prepstatem =null;
      		ResultSet res = null;
      		try {
      			// 加载驱动
      			Class.forName("com.mysql.cj.jdbc.Driver");
      			// 获取连接
      			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
      		
      			// 创建sql语句
      			String sql = "select * from student where sid = ?";
      			
      			// 创建执行sql语句的对象
      			prepstatem = conn.prepareStatement(sql);
      			
      			prepstatem.setObject(1, sid);
      			
      			res = prepstatem.executeQuery();
      			
      			if(res.next()) {
      				s = new Student();
      				s.setSid(res.getInt("sid"));
      				s.setBirthday(res.getDate("birthday"));
      				s.setSname(res.getString("sname"));
      				s.setSsex(res.getString("ssex"));
      				s.setClassid(res.getInt("classid"));
      			}
      			
      		} catch (ClassNotFoundException e) {
      			e.printStackTrace();
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}finally {
      			if(res != null) {
      				try {
      					res.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			if(prepstatem !=null) {
      				try {
      					prepstatem.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			if(conn != null) {
      				try {
      					conn.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			
      		}
      		
      		return s;
      	}
      
      	@Override
      	public List<Student> findAllStudent() {
      
      		List<Student> slist = new ArrayList<Student>();
      		Connection conn = null;
      		PreparedStatement prepstatem = null;
      		ResultSet res = null;
      		try {
      			// 加载驱动
      			Class.forName("com.mysql.cj.jdbc.Driver");
      			// 获取连接
      			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
      			// 创建sql语句
      			String sql = "select * from student";
      			// 创建执行sql语句的对象
      			prepstatem = conn.prepareStatement(sql);
      			// 执行sql语句
      			res = prepstatem.executeQuery();
      			while(res.next()) {
      				Student s = new Student();
      				s.setSid(res.getInt("sid"));
      				s.setSname(res.getString("sname"));
      				s.setBirthday(res.getDate("birthday"));
      				s.setSsex(res.getString("ssex"));
      				s.setClassid(res.getInt("classid"));
      				slist.add(s);
      			}
      			
      		} catch (ClassNotFoundException e) {
      			e.printStackTrace();
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}finally {
      			if(res !=null) {
      				try {
      					res.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			if(prepstatem != null) {
      				try {
      					prepstatem.close();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			if(conn != null) {
      				try {
      					conn.close ();
      				} catch (SQLException e) {
      					// TODO Auto-generated catch block
      					e.printStackTrace();
      				}
      			}
      			
      		}
      		return slist;
      	}
      }
      
    • com.ape.service

      package com.ape.service;
      
      import java.util.List;
      
      import com.ape.bean.Student;
      
      public interface studentService {
      	// 注册
      	public boolean register(Student s);
      	
      	// 信息修改
      	
      	// 详细信息
      	public Student info(int sid);
      	
      	// 全部学生列表
      	public List<Student> stulist(); 
      }
      
    • com.ape.service.impl

      package com.ape.service.impl;
      
      import java.util.List;
      
      import com.ape.bean.Student;
      import com.ape.dao.studentDao;
      import com.ape.dao.impl.studentDaoImpl;
      import com.ape.service.studentService;
      
      public class studentServiceImpl implements studentService{
      
      	@Override
      	public boolean register(Student s) {
      		boolean isok = false;
      		studentDao sd = new studentDaoImpl();
      		int res = sd.addStudent(s);
      		if(res>0) {
      			isok = true;
      		}
      		return isok;
      	}
      
      	@Override
      	public Student info(int sid) {
      		studentDao sd = new studentDaoImpl();
      		Student s = sd.findStudentBySid(sid);
      		return s;
      	}
      
      	@Override
      	public List<Student> stulist() {
      		studentDao sd = new studentDaoImpl();
      		List<Student> slist = sd.findAllStudent();
      		return slist;
      	}
      }
      
    • com.ape.view

      package com.ape.view;
      
      public interface studentView {
      	//学生的注册
      	public void showstuadd();
      	
      	// 学生个人信息
      	public void showstuinfo();
      	
      	// 所有学生的信息
      	public void showstulist();
      	
      	// 学生模块菜单
      	public void showstumenu();
      }
      
    • com.ape.view.impl

      package com.ape.view.impl;
      
      import java.text.ParseException;
      import java.text.SimpleDateFormat;
      import java.util.List;
      import java.util.Scanner;
      
      import com.ape.bean.Student;
      import com.ape.service.studentService;
      import com.ape.service.impl.studentServiceImpl;
      import com.ape.view.studentView;
      
      public class studentViewImpl implements studentView {
      
      	@Override
      	public void showstuadd() {
      		Scanner input = new Scanner(System.in); 
      		
      		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      		
      		System.out.println("添加学生:按照提示信息输入");
      		System.out.println("请输入学生姓名");
      		String sname = input.next();
      		System.out.println("请输入学生的生日");
      		String bir = input.next();
      		System.out.println("请输入学生的性别");
      		String sex = input.next();
      		System.out.println("请输入学生的班级");
      		int classid = input.nextInt();
      		
      		Student s = new Student();
      		try {
      			s.setBirthday(sdf.parse(bir));
      		} catch (ParseException e) {
      			e.printStackTrace();
      		}
      		s.setSname(sname);
      		s.setSsex(sex);
      		s.setClassid(classid);
      		
      		studentService ss = new studentServiceImpl();
      		boolean isok = ss.register(s);
      		if(isok) {
      			System.out.println("添加成功");
      		}else {
      			System.out.println("添加失败");
      		}
      	}
      
      	@Override
      	public void showstuinfo() {
      		Scanner input = new Scanner(System.in);
      		System.out.println("请输入需要查找的学生编号");
      		int sid = input.nextInt();
      		studentService ss = new studentServiceImpl();
      		Student s = ss.info(sid);
      		System.out.println(s);
      	}
      
      	@Override
      	public void showstulist() {
      		studentService ss = new studentServiceImpl();
      		List<Student> stulist = ss.stulist();
      		stulist.forEach(System.out::println);
      	}
      
      	@Override
          // 选项菜单
      	public void showstumenu() {
      		Scanner input = new Scanner(System.in);
      		int key = -1;
      		System.out.println("欢迎使用学生管理系统");
      		do {
      			System.out.println("输入数字1:添加学生,2:查看一个学生的信息,3:查看所有学生,4:修改学生信息,5:开除学生,0:退出程序");
      			if(input.hasNextInt()) {
      				key = input.nextInt();
      				switch(key) {
      				case 1:
      				{
      					showstuadd();
      				}
      				break;
      				case 2:{
      					showstuinfo();
      				}
      				break;
      				case 3:{
      					showstulist();
      				}
      				break;
      				case 4:
      				{
      					System.out.println("功能未开发");
      				}
      				break;
      				case 5:
      				{
      					System.out.println("功能未开发");
      				}
      				break;
      				default:
      					System.out.println("请输入正确编号");
      				break;
      				}
      			}else {
      				System.out.println("请输入菜单中的编号,敲雷瓦");
      				input.next();
      			}
      		}while(key != 0);
      		System.out.println("感谢使用,Bye!");
      		input.close();
      	}
      }
      
    • com.ape.test

      package com.ape.test;
      
      import com.ape.view.studentView;
      import com.ape.view.impl.studentViewImpl;
      
      public class Test01 {
      	// 测试
      	public static void main(String[] args) {
      		studentView sv = new studentViewImpl();
      		sv.showstumenu();
      	}
      }
      

三层架构DAO封装

在DAO层的实现接口类中,发现代码重复率高(如加载驱动,获取连接),此时就可以把相同的代码提取出来进行封装继承,达到提高代码复用率,降低冗余的效果

  1. 包结构

    在这里插入图片描述

    • com.ape.bean:实体类
    • com.ape.dao:DAO层
      1. BaseDao:执行sql语句对象
      2. DaoUtil:加载驱动,获取连接,释放资源
      3. IStudentDao:DAO层接口
    • com.ape.dap.impl:实现DAO接口的类
    • com.ape.test:测试类
  2. 代码实现

    • com.ape.bean:实体类

      同上三层架构中的实体类

    • com.ape.dao:

      1. BaseDao

        package com.ape.dao;
        
        import java.sql.Connection;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        
        public class BaseDao {
        	
         	protected Connection conn;
         	protected PreparedStatement prepstatem;
         	protected ResultSet res;
        	
        	// 增删改
        	public int exeUpdate(String sql , Object...arge) {
        		int ret = 0;
        		try {
        			conn = DaoUtil.getConn();
        			prepstatem = conn.prepareStatement(sql);
        			if(arge != null) {
        				for(int i = 0; i<arge.length ;i++) {
        					prepstatem.setObject(i+1, arge[i]);
        				}
        			}
        			ret = prepstatem.executeUpdate();
        			
        		} catch (SQLException e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		} finally {
        			DaoUtil.closeResourse(conn, prepstatem, res);
        		}
        		return ret;
        	}
        	
        	
        	// 查询
        	public ResultSet exeQuery(String sql,Object...arge) {
        		ResultSet rs = null;
        		
        		try {
        			conn = DaoUtil.getConn();
        			prepstatem = conn.prepareStatement(sql);
        			if(arge != null) {
        				for(int i = 0; i<arge.length ;i++) {
        					prepstatem.setObject(i+1, arge[i]);
        				}
        			}
        			rs = prepstatem.executeQuery();
        		} catch (SQLException e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		} 
        		return rs;
        	}
        }
        

        增删改的返回值都是受影响行数为int类型,而查询的返回值是ResultSet对象

      2. DaoUtil

        package com.ape.dao;
        
        import java.sql.Connection;
        import java.sql.DriverManager;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;
        
        public class DaoUtil {
        	// 加载驱动
        	static{
        		try {
        			Class.forName("com.mysql.cj.jdbc.Driver");
        		} catch (ClassNotFoundException e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		}
        	}
        	
        	// 获取连接
        	public static Connection getConn() {
        		Connection conn = null;
        		try {
        			conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool?serverTimezone=GMT", "root", "123456");
        		} catch (SQLException e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		}
        		return conn;
        	}
        	
        	// 释放资源
        	public static void closeResourse(Connection conn , PreparedStatement prepstatem,ResultSet res) {
        		if(res != null) {
        			try {
        				res.close();
        			} catch (SQLException e) {
        				// TODO Auto-generated catch block
        				e.printStackTrace();
        			}
        		}
        		
        		if(prepstatem != null) {
        			try {
        				prepstatem.close();
        			} catch (SQLException e) {
        				// TODO Auto-generated catch block
        				e.printStackTrace();
        			}
        		}
        		if(conn !=null) {
        			try {
        				conn.close();
        			} catch (SQLException e) {
        				// TODO Auto-generated catch block
        				e.printStackTrace();
        			}
        		}
        	}
        }
        

        驱动只加载一次就可以,可用静态代码块,随着类的加载执行一次

      3. IStudentDao

        package com.ape.dao;
        
        import java.util.List;
        
        import com.ape.bean.Student;
        
        public interface IStudentDao {
        	// 新增
        		public int addStudent(Student s);
        		
        		// 更新
        		public int updateStudent(Student s);
        		
        		// 删除
        		public int deleteStudent(Student s);
        		
        		// 查看
        		public Student findStudentBySid(int sid);
        		public List<Student> findAllStudent();
        }
        
    • com.ape.dap.impl

      package com.ape.dao.impl;
      
      import java.sql.SQLException;
      import java.util.ArrayList;
      import java.util.List;
      
      import com.ape.bean.Student;
      import com.ape.dao.BaseDao;
      import com.ape.dao.IStudentDao;
      
      public class StudentDaoImpl extends BaseDao implements IStudentDao{
      
      	@Override
      	public int addStudent(Student s) {
      		String sql = "insert into student(sname,birthday,ssex,classid) values (?,?,?,?)";
      		return exeUpdate(sql, s.getSname(),s.getBirthday(),s.getSsex(),s.getClassid());
      	}
      
      	// 修改
      	@Override
      	public int updateStudent(Student s) {
      		String sql = "update student set sname =?,birthday=?,ssex=?,classid=? where sid = ?";
      		return exeUpdate(sql, s.getSname(),s.getBirthday(),s.getSsex(),s.getClassid(),s.getSid());
      	}
      
      	// 删除
      	@Override
      	public int deleteStudent(Student s) {
      		String sql = "delete from student where sid = ?";
      		return exeUpdate(sql, s.getSid());
      	}
      
      	// 通过sid查找学生
      	@Override
      	public Student findStudentBySid(int sid) {
      		Student s = null;
      		try {
      			String sql = "select * from student where sid = ?";
      			res = exeQuery(sql, sid);
                  // 解析结果
      			if(res.next()) {
      				s  = new Student();
      				s.setSid(res.getInt("sid"));
      				s.setSname(res.getString("sname"));
      				s.setBirthday(res.getDate("birthday"));
      				s.setSsex(res.getString("ssex"));
      				s.setClassid(res.getInt("classid"));
      			}
      		} catch (SQLException e) {
      			// TODO Auto-generated catch block
      			e.printStackTrace();
      		}
      		return s;
      	}
      
      	@Override
      	public List<Student> findAllStudent() {
      		List<Student> slist = new ArrayList<Student>();
      		try {
      			String sql = "select * from student";
      			res = exeQuery(sql);
                  // 解析结果
      			while(res.next()) {
      				Student s = new Student();
      				s.setSid(res.getInt("sid"));
      				s.setSname(res.getString("sname"));
      				s.setBirthday(res.getDate("birthday"));
      				s.setSsex(res.getString("ssex"));
      				s.setClassid(res.getInt("classid"));
      				slist.add(s);
      			}
      		} catch (SQLException e) {
      			// TODO Auto-generated catch block
      			e.printStackTrace();
      		}
      		return slist;
      	}
      }
      

      通过继承BaseDao类和实现dao层接口,使得方法中的语句大大的减少

    • com.ape.test

      package com.ape.test;
      
      import java.text.ParseException;
      import java.text.SimpleDateFormat;
      
      import com.ape.bean.Student;
      import com.ape.dao.impl.StudentDaoImpl;
      
      public class Test {
      	public static void main(String[] args) {
      		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      		StudentDaoImpl sdi = new StudentDaoImpl();
      		//新增学生
      		Student s = new Student();
      		s.setSname("王忠");
      		s.setSsex("男");
      		try {
      			s.setBirthday(sdf.parse("1999-7-7"));
      		} catch (ParseException e) {
      			// TODO Auto-generated catch block
      			e.printStackTrace();
      		}
      		s.setClassid(3);
      		System.out.println(sdi.addStudent(s));
              
              // 修改:略
              // 删除:略
              
      		// 通过id查询学生个人信息
      		System.out.println(sdi.findStudentBySid(2));
      		// 查询所有学生信息
      		sdi.findAllStudent().forEach(System.out::println);
      	}
      }
      
      

连接池技术

  • 数据库连接池
  1. ​ 概念:其实就是一个容器(集合),存放数据库连接的容器。

    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

  2. 好处:

    • 节约资源

    • 用户访问高效

  3. 实现:

  • 标准接口:DataSource javax.sql包下的

    1. 方法:

      获取连接:getConnection()

      归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接

    2. 一般我们不去实现它,有数据库厂商来实现

​ 1. C3P0:数据库连接池技术

​ 2. Druid:数据库连接池实现技术,由阿里巴巴提供的

C3P0

  • 步骤
  1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,*不要忘记导入数据库驱动jar包

  2. 定义配置文件:

名称: c3p0.properties 或者 c3p0-config.xml文件名称不可以修改

路径:直接将文件放在src目录下即可,路径不可修改

  1. 创建核心对象 数据库连接池对象 ComboPooledDataSource

  2. 获取连接: getConnection

  • 源代码实现

    1. DaoUtilC3P0

      package com.ape.test;
      
      import java.sql.Connection;
      import java.sql.SQLException;
      
      import javax.sql.DataSource;
      
      import com.mchange.v2.c3p0.ComboPooledDataSource;
      
      public class DaoUtilC3P0 {
      	private static DataSource ds;
      	static {
      		ds = new ComboPooledDataSource();
      	}
      	
      	public Connection getConn() {
      		Connection conn = null;
      		try {
      			conn=ds.getConnection();
      		} catch (SQLException e) {
      			// TODO Auto-generated catch block
      			e.printStackTrace();
      		}
      		return conn;
      	}
      }
      
    2. Test

    package com.ape.test;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class Test {
    	public static void main(String[] args) throws SQLException {
    		// 连接池
    		DataSource ds = new ComboPooledDataSource();
    		
    		Connection conn = ds.getConnection();
    		
    		System.out.println(conn);
    		
    		conn.close();// 还到池子中
    	}
    }
    

druid(德鲁伊)

Druid:数据库连接池实现技术,由阿里巴巴提供的

  • 步骤:
  1. 导入jar包 druid-1.0.9.jar

  2. 定义配置文件:

    是properties形式的

    可以叫任意名称,可以放在任意目录下

  3. 加载配置文件。Properties

    1. 获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
    2. 获取连接:getConnection
  • 代码实现

    package com.ape.test;
    
    import java.io.FileInputStream;
    import java.sql.Connection;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    public class test {
    	public static void main(String[] args) throws Exception {
    		// 读取配置文件
    		Properties pro = new Properties();
    		FileInputStream input = new FileInputStream("./src/druid.properties");
    		pro.load(input);
    		
    		// 创建连接池 -- 德鲁伊
    		DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    		
    		Connection conn = ds.getConnection();
    		
    		System.out.println(conn);
    		
    		conn.close();
    	}
    }
    

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMonkey-D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值