JDBC Java DataBase Connectivity java数据库连接
首先是由Java提供的一套接口 不同的数据库厂商去实现这些接口 从而实现和数据库的连接
接口 java.sql包中
反射 通过包名 + 类名 来获取一个类类型的对象
必须使用 与之对应的数据库厂商提供的 相关的类 jar
1.导入jar包
2.使用反射的方式 加载驱动
3.通过驱动管理类 获取一个连接对象
4.有了连接对象 还需要操作sql的对象
5.编写sql语句
6.通过statement对象来执行sql语句
7.将数据从结果集中取出来
8.关闭资源
根据id进行删除
package com.qfedu.test1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class TestDeleteByID { public static void main(String[] args) { Connection conn = null; Statement statement = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/zz206", "root", "9999"); statement = conn.createStatement(); Scanner input = new Scanner(System.in); System.out.println("请输入你要删除的编号"); int sid = input.nextInt(); String sql = "delete from stu where sid =" + sid; int resultRowCount = statement.executeUpdate(sql); if(resultRowCount == 1) { System.out.println("删除成功"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { if(statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }根据name进行删除
package com.qfedu.test1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.util.Scanner; public class TestDeleteByName { public static void main(String[] args) { Connection conn = null; Statement statement = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/zz206", "root", "9999"); statement = conn.createStatement(); Scanner input = new Scanner(System.in); System.out.println("请输入你要删除的名字"); String name = input.next(); String sql = "delete from stu where sname ='" + name + "'" ; int resultRowCount = statement.executeUpdate(sql); if(resultRowCount == 1) { System.out.println("删除成功"); }else { System.out.println("删除失败"); } }catch(Exception e){ } } }之前我们使用Statement对象操作sql语句 可以实现功能 但是有一些弊端
1.在传输参数的时候 我们需要加很多单引号
2.这种方式不能避免 sql注入 对系统有很大的安全隐患
所以我们换一种方式来实现对数据库的操作
JDK提供的有另外一个接口 PreparedStatement 预编译的sql执行对象
PreparedStatement属于Statement的子接口
查询优化
package com.qfedu.test1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; import com.mysql.jdbc.Driver; /** * 之前我们使用Statement对象操作sql语句 可以实现功能 但是有一些弊端 * 1.在传输参数的时候 我们需要加很多单引号 * 2.这种方式不能避免 sql注入 对系统有很大的安全隐患 * 所以我们换一种方式来实现对数据库的操作 * JDK提供的有另外一个接口 PreparedStatement 预编译的sql执行对象 * PreparedStatement属于Statement的子接口 * @author WHD * */ public class TestQuery { public static void main(String[] args) { try { // 加载驱动 加载当前类到JVM虚拟机中 // Drvier d = new Driver(); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/zz206", "root", "9999"); Scanner input = new Scanner(System.in); System.out.println("请输入你要查询的名字"); String name = input.nextLine(); // 占位符 占一个位置 用于给还未传入的参数 占定一个位置 等待我们在执行sql之前将参数传入 String sql = "select * from stu where sname = ?"; PreparedStatement ps = conn.prepareStatement(sql); System.out.println(ps); ps.setString(1, name); System.out.println(ps); ResultSet rs = ps.executeQuery(); if(rs.next()) { // rs.getInt(1); System.out.println(rs.getInt("sid") + "\t" + rs.getString(2) + "\t" + rs.getString("saddress") + rs.getString("sex") + "\t" + rs.getDate("sborndate")+ "\t" + rs.getInt("sage") + "\t" + rs.getString("semail")+ "\t" + rs.getString("pwd")); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { // 关闭资源 } } }增加优化
package com.qfedu.test1; import java.sql.Connection; import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class TestInsert { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/zz206", "root", "9999"); String sql = "insert into stu(sname,saddress,sex,sborndate,sage,semail,pwd) values(?,?,?,?,?,?,?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, "蔡徐坤"); ps.setString(2,"篮球场"); ps.setString(3, "男"); ps.setDate(4, new Date(System.currentTimeMillis())); ps.setInt(5, 17); ps.setString(6, "1235@163.com"); ps.setString(7, "8956zz"); int result = ps.executeUpdate(); System.out.println(result == 1 ? "成功" : "失败"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { // 关闭资源 } } }1.编写一个用户获取连接对象的方法
2.关闭资源的方法
①连接对象
②statement对象
③结果集对象
先进行非null判断
遵循一个 先用后关
查询名字
package com.qfedu.test2; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; import com.mysql.jdbc.Driver; import com.qfedu.util.ConnectionUtil; public class TestQueryUseUtil { public static void main(String[] args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 加载驱动 加载当前类到JVM虚拟机中 // Driver d = new Driver(); // Class.forName("com.mysql.jdbc.Driver"); // Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/zz206", "root", "9999"); conn = ConnectionUtil.getConn(); Scanner input = new Scanner(System.in); System.out.println("请输入你要查询的名字"); String name = input.nextLine(); // 占位符 占一个位置 用于给还未传入的参数 占定一个位置 等待我们在执行sql之前将参数传入 String sql = "select * from stu where sname = ?"; ps = conn.prepareStatement(sql); System.out.println(ps); ps.setString(1, name); System.out.println(ps); rs = ps.executeQuery(); if(rs.next()) { // rs.getInt(1); System.out.println(rs.getInt("sid") + "\t" + rs.getString(2) + "\t" + rs.getString("saddress") + rs.getString("sex") + "\t" + rs.getDate("sborndate")+ "\t" + rs.getInt("sage") + "\t" + rs.getString("semail")+ "\t" + rs.getString("pwd")); } } catch (SQLException e) { e.printStackTrace(); }finally { // 关闭资源 ConnectionUtil.closeResource(conn, ps, rs); } } }增加
package com.qfedu.test2; import java.sql.Connection; import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import com.qfedu.util.ConnectionUtil; public class TestInsertUseUtil { public static void main(String[] args) { Connection conn = null; PreparedStatement ps = null; try { // Class.forName("com.mysql.jdbc.Driver"); // Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/zz206", "root", "9999"); conn = ConnectionUtil.getConn(); String sql = "insert into stu(sname,saddress,sex,sborndate,sage,semail,pwd) values(?,?,?,?,?,?,?)"; ps = conn.prepareStatement(sql); ps.setString(1, "蔡徐坤"); ps.setString(2,"篮球场"); ps.setString(3, "男"); ps.setDate(4, new Date(System.currentTimeMillis())); ps.setInt(5, 17); ps.setString(6, "1235@163.com"); ps.setString(7, "8956zz"); int result = ps.executeUpdate(); System.out.println(result == 1 ? "成功" : "失败"); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { // 关闭资源 ConnectionUtil.closeResource(conn, ps, null); } } }实体类 包命名 entity pojo
此包中存放的是和数据库中表一一对应的实体类
每个实体类相当于数据的载体
要求:
1.表名和类名要一致
2.列名和属性名要一致
package com.qfedu.entity; import java.util.Date; /** * 实体类 包命名 entity pojo * 此包中存放的是和数据库中表一一对应的实体类 * 每个实体类相当于数据的载体 * 要求: * 1.表名和类名要一致 * 2.列名和属性名要一致 * @author WHD * */ public class Student { private Integer sid; private String sName; private String sex; private Date sBornDate; private Integer sAge; private String sEmail; private String pwd; private Integer cityId; public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getsName() { return sName; } public void setsName(String sName) { this.sName = sName; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getsBornDate() { return sBornDate; } public void setsBornDate(Date sBornDate) { this.sBornDate = sBornDate; } public Integer getsAge() { return sAge; } public void setsAge(Integer sAge) { this.sAge = sAge; } public String getsEmail() { return sEmail; } public void setsEmail(String sEmail) { this.sEmail = sEmail; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public Integer getCityId() { return cityId; } public void setCityId(Integer cityId) { this.cityId = cityId; } public Student() { } public Student(Integer sid, String sName, String sex, Date sBornDate, Integer sAge, String sEmail, String pwd, Integer cityId) { this.sid = sid; this.sName = sName; this.sex = sex; this.sBornDate = sBornDate; this.sAge = sAge; this.sEmail = sEmail; this.pwd = pwd; this.cityId = cityId; } @Override public String toString() { return "Student [sid=" + sid + ", sName=" + sName + ", sex=" + sex + ", sBornDate=" + sBornDate + ", sAge=" + sAge + ", sEmail=" + sEmail + ", pwd=" + pwd + ", cityId=" + cityId + "]"; } }DAO Data Access Object 对象访问模型
此类中提供只有功能 关于某一个表的增删改查功能
此类中只有抽象方法
方法命名
动作 + 对象 + 条件
获取内容 get
删除 remove delete
修改 update modify
新增 add
By + 条件
学生
package com.qfedu.dao.impl; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.qfedu.dao.BaseDao; import com.qfedu.dao.StudentDao; import com.qfedu.entity.Student; public class StudentDaoImpl extends BaseDao implements StudentDao{ @Override public Student getStudentByName(String sName) { // 占位符 占一个位置 用于给还未传入的参数 占定一个位置 等待我们在执行sql之前将参数传入 String sql = "select * from student where sname = ?"; Object [] obj = {sName}; ResultSet rs = this.getData(sql, new Object[] {sName}); Student stu = new Student(); try { if(rs.next()) { stu.setSid(rs.getInt("sid")); stu.setsName(rs.getString(2)); stu.setSex(rs.getString("sex")); stu.setsBornDate(rs.getDate("sborndate")); stu.setsAge(rs.getInt("sage")); stu.setsEmail(rs.getString("semail")); stu.setPwd(rs.getString("pwd")); stu.setCityId(rs.getInt("cityid")); } } catch (SQLException e) { e.printStackTrace(); }finally { this.closeResource(); } return stu; } @Override public List<Student> getAllStudent() { List<Student> list = new ArrayList<Student>(); try { String sql = "select * from student"; ResultSet rs = this.getData(sql); while(rs.next()) { Student stu = new Student(); stu.setSid(rs.getInt("sid")); stu.setsName(rs.getString(2)); stu.setSex(rs.getString("sex")); stu.setsBornDate(rs.getDate("sborndate")); stu.setsAge(rs.getInt("sage")); stu.setsEmail(rs.getString("semail")); stu.setPwd(rs.getString("pwd")); stu.setCityId(rs.getInt("cityid")); list.add(stu); } }catch(SQLException e) { e.printStackTrace(); }finally { this.closeResource(); } return list; } @Override public int addStudent(Student stu) { String sql; try { sql = "insert into student(sname,sex,sborndate,sage,semail,pwd,cityid) values(?,?,?,?,?,?,?)"; Object[] obj={stu.getsName(),stu.getSex(),stu.getsBornDate(),stu.getsAge(),stu.getsEmail(),stu.getPwd(),stu.getCityId()}; return this.modifyData(sql, obj); } catch (Exception e) { e.printStackTrace(); }finally { this.closeResource(); } return 0; } @Override public int deleteStudentById(Integer sId) { try { String sql = "delete from student where sid = ?"; return this.modifyData(sql, new Object[] {sId}); } catch (Exception e) { e.printStackTrace(); }finally { this.closeResource(); } return 0; } @Override public List<Student> getStudentByCityId(Integer cityId) { String sql = "select * from student where cityid = ?"; ResultSet rs = this.getData(sql, new Object[] {cityId}); List<Student> list = new ArrayList<Student>(); try { while(rs.next()) { Student stu = new Student(); stu.setSid(rs.getInt("sid")); stu.setsName(rs.getString(2)); stu.setSex(rs.getString("sex")); stu.setsBornDate(rs.getDate("sborndate")); stu.setsAge(rs.getInt("sage")); stu.setsEmail(rs.getString("semail")); stu.setPwd(rs.getString("pwd")); stu.setCityId(rs.getInt("cityid")); list.add(stu); } } catch (SQLException e) { e.printStackTrace(); }finally { this.closeResource(); } return list; } }城市
package com.qfedu.dao.impl; import com.qfedu.dao.BaseDao; import com.qfedu.dao.CityDao; public class CityDaoImpl extends BaseDao implements CityDao{ @Override public int deleteCityById(Integer cityId) { int result = 0; try { String sql = "delete from city where cid = ?"; result = this.modifyData(sql, new Object[] {cityId}); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { this.closeResource(); } return result; } }本类作为dao类的基类 也就是 父类
本类中提供两个方法
1.查询的方法 executeQuery();
2.增删改查的方法 executeUpdate();
分析 不管是什么情况下的查询 都需要sql语句 也需要参数 但是参数的个数、类型是不同 所以我们可以编写一个用于
所有条件的查询的方法 从而简化我们dao实现类的代码 所有的查询都会返回一个 ResultSet结果集
package com.qfedu.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.qfedu.util.ConnectionUtilUseProperties; /** * 本类作为dao类的基类 也就是 父类 * 本类中提供两个方法 * 1.查询的方法 executeQuery(); * 2.增删改查的方法 executeUpdate(); * 分析 不管是什么情况下的查询 都需要sql语句 也需要参数 但是参数的个数、类型是不同 所以我们可以编写一个用于 * 所有条件的查询的方法 从而简化我们dao实现类的代码 所有的查询都会返回一个 ResultSet结果集 * @author WHD * */ public class BaseDao { public ResultSet getData(String sql , Object ...args) { Connection conn = ConnectionUtilUseProperties.getConn(); ResultSet rs = null; try { PreparedStatement ps = conn.prepareStatement(sql); // 以上代码我们获取到一个 ps 预编译执行sql对象 // 1. sql语句不需要传入 任何的参数 比如 select * from student // 2. sql语句需要传入不确定的参数 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); } catch (SQLException e) { e.printStackTrace(); } return rs; } }继承Dao的父类BaseDao
package com.qfedu.dao.impl; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.qfedu.dao.BaseDao; import com.qfedu.dao.StudentDao; import com.qfedu.entity.Student; import com.qfedu.util.ConnectionUtil; import com.qfedu.util.ConnectionUtilUseProperties; public class StudentDaoImpl extends BaseDao implements StudentDao{ @Override public Student getStudentByName(String sName) { // 占位符 占一个位置 用于给还未传入的参数 占定一个位置 等待我们在执行sql之前将参数传入 String sql = "select * from student where sname = ?"; Object [] obj = {sName}; ResultSet rs = this.getData(sql, new Object[] {sName}); Student stu = new Student(); try { if(rs.next()) { stu.setSid(rs.getInt("sid")); stu.setsName(rs.getString(2)); stu.setSex(rs.getString("sex")); stu.setsBornDate(rs.getDate("sborndate")); stu.setsAge(rs.getInt("sage")); stu.setsEmail(rs.getString("semail")); stu.setPwd(rs.getString("pwd")); stu.setCityId(rs.getInt("cityid")); } } catch (SQLException e) { e.printStackTrace(); } return stu; } @Override public List<Student> getAllStudent() { List<Student> list = new ArrayList<Student>(); PreparedStatement ps = null; ResultSet rs = null; Connection conn = null; try { conn = ConnectionUtilUseProperties.getConn(); ps = conn.prepareStatement("select * from student"); rs = ps.executeQuery(); while(rs.next()) { Student stu = new Student(); stu.setSid(rs.getInt("sid")); stu.setsName(rs.getString(2)); stu.setSex(rs.getString("sex")); stu.setsBornDate(rs.getDate("sborndate")); stu.setsAge(rs.getInt("sage")); stu.setsEmail(rs.getString("semail")); stu.setPwd(rs.getString("pwd")); stu.setCityId(rs.getInt("cityid")); list.add(stu); } return list; } catch (SQLException e) { e.printStackTrace(); }finally { ConnectionUtilUseProperties.closeResource(conn, ps, rs); } return null; } @Override public int addStudent(Student stu) { Connection conn = ConnectionUtilUseProperties.getConn(); String sql = "insert into student(sname,sex,sborndate,sage,semail,pwd,cityid) values(?,?,?,?,?,?,?)"; PreparedStatement ps = null; try { ps = conn.prepareStatement(sql); ps.setString(1, stu.getsName()); ps.setString(2, stu.getSex()); ps.setDate(3, new Date(stu.getsBornDate().getTime())); ps.setInt(4, stu.getsAge()); ps.setString(5, stu.getsEmail()); ps.setString(6, stu.getPwd()); ps.setInt(7, stu.getCityId()); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { ConnectionUtilUseProperties.closeResource(conn, ps, null); } return 0; } @Override public int deleteStudentById(Integer sId) { Connection conn = ConnectionUtilUseProperties.getConn(); String sql = "delete from student where sid = ?"; PreparedStatement ps = null; try { ps = conn.prepareStatement(sql); ps.setInt(1, sId); return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { ConnectionUtilUseProperties.closeResource(conn, ps, null); } return 0; } }为什么我们要编写一个service层
mvc模式 不属于设计模式 是前辈长期开发过程中总结出来的一套用于web开发的经验流程
m model 数据模型层 dao层 dao data access object(对象访问模型) 负责每个表的增删改查
service层不属于mvc层内直接指定的一层 但是实际开发都会有 主要用于业务逻辑的处理
v view 视图层 (jsp,html) 展示数据 给用户看的 将dao层获取的数据显示在页面上 但是不是直接去dao层获取
c control 控制器 (servlet,controller)
package com.qfedu.service; import java.util.List; import com.qfedu.entity.Student; /** * 为什么我们要编写一个service层 * mvc模式 不属于设计模式 是前辈长期开发过程中总结出来的一套用于web开发的经验流程 * m model 数据模型层 dao层 dao data access object(对象访问模型) 负责每个表的增删改查 * service层不属于mvc层内直接指定的一层 但是实际开发都会有 主要用于业务逻辑的处理 * * v view 视图层 (jsp,html) 展示数据 给用户看的 将dao层获取的数据显示在页面上 但是不是直接去dao层获取 * c control 控制器 (servlet,controller) * @author WHD * */ public interface StudentService { boolean deleteCityAndGetStudent(Integer cityId); Student getStudentByName(String sName); List<Student> getAllStudent(); int addStudent(Student stu); int deleteStudentById(Integer sId); List<Student> getStudentByCityId(Integer cityId); }序列化是用于保证序列化和反序列的唯一标识·
package com.qfedu.exception; public class RemoveCityException extends RuntimeException{ // 序列化是用于保证序列化和反序列的唯一标识· private static final long serialVersionUID = 1L; public RemoveCityException(String message) { super(message); } }第一种实现方式 使用boolean类型作为返回值
第二种实现方式 如果不能删除 抛出一个异常
package com.qfedu.service.impl; import java.util.List; import com.qfedu.dao.CityDao; import com.qfedu.dao.StudentDao; import com.qfedu.dao.impl.CityDaoImpl; import com.qfedu.dao.impl.StudentDaoImpl; import com.qfedu.entity.Student; import com.qfedu.exception.RemoveCityException; import com.qfedu.service.StudentService; public class StudentServiceImpl implements StudentService{ StudentDao sd = new StudentDaoImpl(); CityDao cd = new CityDaoImpl(); @Override public boolean deleteCityAndGetStudent(Integer cityId) { // 第一种实现方式 使用boolean类型作为返回值 // List<Student> list = sd.getStudentByCityId(cityId); // int result = 0; // if(list.size() == 0) { // result = cd.deleteCityById(cityId); // } // if(result != 0) { // return true; // } // return false; // 第二种实现方式 如果不能删除 抛出一个异常 List<Student> list = sd.getStudentByCityId(cityId); if(list.size() != 0) { throw new RemoveCityException("删除城市下还有学生"); } int result = 0; result = cd.deleteCityById(cityId); return result != 0; } @Override public Student getStudentByName(String sName) { return sd.getStudentByName(sName); } @Override public List<Student> getAllStudent() { return sd.getAllStudent(); } @Override public int addStudent(Student stu) { return sd.addStudent(stu); } @Override public int deleteStudentById(Integer sId) { return sd.deleteStudentById(sId); } @Override public List<Student> getStudentByCityId(Integer cityId) { return sd.getStudentByCityId(cityId); } }junit
@Test必写
package com.qfedu.test; import java.util.List; import org.junit.Test; import com.qfedu.entity.Student; import com.qfedu.service.StudentService; import com.qfedu.service.impl.StudentServiceImpl; /** * 右键 new一个 junit测试用例 单元测试 * @author WHD * */ public class MyTest { StudentService ss = new StudentServiceImpl(); @Test public void test1() { List<Student> list = ss.getAllStudent(); System.out.println(list); } @Test public void test2() { Student stu = ss.getStudentByName("赵四"); System.out.println(stu); } @Test public void test3() { } }