Java 数据库程序设计(JDBC)
补:数据库的基本操作
JDBC的基本概念
全称: Java Data Base Connectivity
组成:
由一组用Java语言编写的类和接口组成,不同的数据库都会实现这种接口。
作用:
为多种关系数据库提供同一的接口
优点:
对于不同厂商的数据库,JDBC驱动包都相同。
一次编写,处处运行
JAR包:
用JAVA语言实现与数据库的交互,是直接访问数据库,执行效率高
编程步骤:
- 加载数据库驱动:告知JVM使用的是哪一个数据库的驱动
- 连接数据库。
- 创建SQL语句的执行者对象。
- 执行sql语句:使用执行者对象,向数据库执行SQL语句 获取到数据库的执行后的结果
- 处理结果。
- 关闭SQL语句执行对象 。
- 关闭连接。
- 程序结束。
常用API
Driver接口
概念:
Driver接口由数据库厂家提供。在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序,不同的数据库有不同的装载方法。
用到的实现类:JAVA.lang.Class
方法:
装载驱动:Class.forName(String className);
返回与 给定字符串名的类或接口 相关联的Class对象。 ---加载JDBC驱动时使用
装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");
Connection接口
作用:
与特定数据库的连接,和创建向数据库发送sql的statement对象。
用到的实现类:JAVA.sql.DruverMannager
连接数据库方法:
Connction getConnection (String url ,String user, String password)
---获取url对应的数据库的链接
连接MySql数据库:
Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
创建statement对象方法:
createStatement():创建向数据库发送sql的statement对象。
prepareStatement(String sql) :创建向数据库发送预编译sql的PrepareSatement对象。
Statement接口
作用:
用于执行SQL语句并返回它所生成结果的对象。
用到的实现类:
Statement:
由createStatement创建,用于发送简单的SQL语句(不带参数)。
PreparedStatement :
继承自Statement接口,由preparedStatement创建,用于发送含有一个或多个参数的SQL语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,一般都使用PreparedStatement。
常用Statement方法:
executeQuery(String sql):运行select语句,返回ResultSet结果集。
executeUpdate(String sql):运行insert/update/delete操作,返回更新的行数。
ResultSet接口
作用:
提供检索不同类型字段的方法。
用到的实现类:ResultSet
获取信息的方法
getString(int index)、getString(String columnName):获得在数据库里是varchar、char等类型的数据对象。
getFloat(int index)、getFloat(String columnName):获得在数据库里是Float类型的数据对象。
getDate(int index)、getDate(String columnName):获得在数据库里是Date类型的数据。
getBoolean(int index)、getBoolean(String columnName):获得在数据库里是Boolean类型的数据。
getObject(int index)、getObject(String columnName):获取在数据库里任意类型的数据。
对结果集进行滚动的方法:
next():移动到下一行
Previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面。
afterLast() :移动到resultSet的最后面。
代码实现
编程步骤
-
加载数据库驱动:
Class.forName("...")
告知JVM使用的是哪一个数据库的驱动 -
连接数据库:
DriverManager.getConnection(url,user,password)
->con -
创建SQL语句的执行者对象:
con.createStatement()
或者con.PreparedStatement()
->st -
执行sql语句:
st.executeUpdate("...")
或者st.executeQuery("...")
使用执行者对象,向数据库执行SQL语句 获取到数据库的执行后的结果 -
处理结果
-
关闭SQL语句执行对象 :
st.close;
-
关闭连接:
con.close();
-
程序结束
基础JDBC
固定语句的JDBC管理
准备
新建JAVA project
新建lib文件夹
粘贴mysql-connector-java-5.1.18-bin.jar到lib文件夹下
在.jar下右键,选择如下
连接数据库+插入
package cn.sdut.text; import static java.sql.DriverManager.getConnection; import java.sql.Connection; import java.sql.SQLException; import com.mysql.jdbc.Statement; public class JDBCText { public static void main(String[] args) throws ClassNotFoundException, SQLException { // TODO Auto-generated method stub //加载JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); //获取数据库的链接 Connection con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/book","root","usbw"); //准备SQL语句执行对象 Statement st=(Statement) con.createStatement(); // 准备SQL语句 String sql= "insert into student values(null,'JOHN',22)"; //执行SQL语句 int result= st.executeUpdate(sql); System.out.println(result>0?"成功":"失败"); //关闭SQL语句执行对象 st.close(); //关闭数据库链接 con.close(); } }
遍历输出
//准备SQL语句 String selectSql="select *from student"; //执行SQL语句 ResultSet rs = st.executeQuery(selectSql);//和增删改不一样 //如果指针还有元素则输出 while(rs.next()) { int stuId=rs.getInt(1); String stuName=rs.getString("name"); String stuIn=rs.getString(3); int StuScore=rs.getInt(4); System.out.println(stuId+" "+stuName+" "+stuIn+" "+StuScore); }
单条查询:
String selectSql1 = "select *from student where id=3"; ResultSet rs2 = st.executeQuery(selectSql1);//和增删改不一样 System.out.println("id为3的数据为:"); if (rs2.next()) { int stuId = rs2.getInt(1); String stuName = rs2.getString("name"); String stuIn = rs2.getString(3); int StuScore = rs2.getInt(4); System.out.println(stuId + " " + stuName + " " + stuIn + " " + StuScore); } else { System.out.println("没有查询到id=3的数据"); }
删除
// 删除id为1的数据 String deleteSql1 = "delete from student where id=1"; int deleteResult1 = st.executeUpdate(deleteSql1); System.out.println(deleteResult1 > 0 ? "id为1的数据删除成功" : "id为1的数据删除失败(可能是因为id为1的数据不存在)");
更新数据
// 修改id=2的数据 String updataSql1 = "update student set name='山东理工' where id=2"; int updataResult1 = st.executeUpdate(updataSql1); System.out.println(updataResult1 > 0 ? "修改id为2的数据成功" : "修改id为2的数据失败(可能是因为id为2的数据不存在)");
输入变量JDBC
方法1:
更改准备SQL语句阶段
// 准备SQL语句 String name="里斯"; int age=20; String sql= "insert into student values(null,'"+name+"',"+age+")";
但是比较复杂。
方法2:
PreparedStatement代替Statement
优点:
- 速度快
- 可以防止SQL注入
package cn.sdut.text; import static java.sql.DriverManager.getConnection; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import com.mysql.jdbc.PreparedStatement; import com.mysql.jdbc.Statement; public class JDBCText { public static void main(String[] args) throws ClassNotFoundException, SQLException { // TODO Auto-generated method stub //加载JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); //获取数据库的链接 Connection con = getConnection("jdbc:mysql://localhost:3306/book","root","usbw"); //准备SQL语句执行对象 java.sql.PreparedStatement pst=null; // 准备SQL语句 String name="里斯22"; int age=20; String sq14="insert into student values(null,?,?)"; pst=(PreparedStatement) con.prepareStatement(sq14); pst.setString(1,name); pst.setInt(2, age); String sql="select * from student"; String sql3="select * from student where id=?"; //执行SQL语句 int result= pst.executeUpdate(); System.out.println(result>0?"成功":"失败"); //遍历输出 pst=con.prepareStatement(sql); ResultSet rs=pst.executeQuery(); while(rs.next()) { int id1=rs.getInt(1); String name1=rs.getString("name"); int age1=rs.getInt(3); System.out.println(id1+" "+name1+" "+age1); } System.out.println("-----------------------"); pst=con.prepareStatement(sql3); pst.setInt(1, 4); ResultSet rs1 = pst.executeQuery(); if(rs1.next()) { int id1=rs1.getInt(1); String name1=rs1.getString("name"); int age1=rs1.getInt(3); System.out.println(id1+" "+name1+" "+age1); } else System.out.println("无此人"); rs.close(); rs1.close(); //关闭SQL语句执行对象 pst.close(); //关闭数据库链接 con.close(); } }
面向对象JDBC
//数据类
package Work; public class Student { private int id=-1; private String name=null; private String date=null; private int score=-1; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } public Student(int id, String name, String date, int score) { super(); this.id = id; this.name = name; this.date = date; this.score = score; } public Student() { super(); } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", date=" + date + ", score=" + score + "]"; } }
//面向对象JDBC类
package Work; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; public class ClassJdbc { Connection con; PreparedStatement pst; ResultSet rs; // 获取数据库连接 public Connection getConnection() throws Exception { // 加载jdbc驱动 Class.forName("com.mysql.jdbc.Driver"); // 获取数据库的连接 Connection con = (Connection) DriverManager.getConnection( "jdbc:mysql://localhost:3306/book?useunicode=true&characterEncoding=utf-8", "root", "usbw"); return con; } public int addStu(Student stu) throws Exception { con = getConnection(); String sql = "insert into student values (null,?,?,?)"; pst = (PreparedStatement) con.prepareStatement(sql); pst.setString(1, stu.getName()); pst.setString(2, stu.getDate()); pst.setInt(3, stu.getScore()); int result = pst.executeUpdate(); End(); return result; } // 删除对象 public int deleteStu(int id) throws Exception { con = getConnection(); String sql = "delete from student where id=?"; pst = (PreparedStatement) con.prepareStatement(sql); pst.setInt(1, id); int result = pst.executeUpdate(); End(); return result; } // 更新数据 public int updateStu(Student stu) throws Exception { String sql = "update student set name=?,schoolin=?,score=? where id=?"; //先查询到待更新的数据,(因为每次不一定要更新全部数据) Student data = getStu(stu.getId()); //获取数据库连接 con = getConnection(); pst = (PreparedStatement) con.prepareStatement(sql); //如果更新的数据某项为空,则设置原来的数据。(初始化默认为空) if (stu.getName() != null) { pst.setString(1, stu.getName()); } else { pst.setString(1, data.getName()); } //如果更新的数据某项为空,则设置原来的数据。(初始化默认为空) if (stu.getDate() != null) { pst.setString(2, stu.getDate()); } else { pst.setString(2, data.getDate()); } //如果更新的数据某项为空,则设置原来的数据。(初始化默认为-1) if (stu.getScore() != -1) { pst.setInt(3, stu.getScore()); } else { pst.setInt(3, data.getScore()); } //因为更新数据id一定存在,所以不需要判断 pst.setInt(4, stu.getId()); int result = pst.executeUpdate(); End(); return result; } // 遍历输出数据 public List<Student> getStuAll() throws Exception { con = getConnection(); //利用List储存查询到的数据 List<Student> stuAll = new ArrayList<Student>(); String sql = "select *from student"; pst = (PreparedStatement) con.prepareStatement(sql); rs = pst.executeQuery(); //如果指针不为空,则代表有元素,继续向下处理数据 while (rs.next()) { //处理数据 Student stu = new Student(); stu.setId(rs.getInt(1)); stu.setName(rs.getString(2)); stu.setDate(rs.getString(3)); stu.setScore(rs.getInt(4)); //将数据存入List stuAll.add(stu); } End(); return stuAll; } // 依据id,查询数据 public Student getStu(int id) throws Exception { con = getConnection(); Student stu = new Student(); String sql = "select *from student where id=?"; pst = (PreparedStatement) con.prepareStatement(sql); pst.setInt(1, id); rs = pst.executeQuery(); if (rs.next()) { stu.setId(rs.getInt(1)); stu.setName(rs.getString(2)); stu.setDate(rs.getString(3)); stu.setScore(rs.getInt(4)); } else stu.setId(-1);//如果id为-1,代表数据未查询到 End(); return stu; } // 关闭对象,收尾。 public void End() throws SQLException { if (rs != null) rs.close(); if (pst != null) pst.close(); if (con != null) con.close(); } public static void main(String[] args) throws Exception { ClassJdbc jdbc = new ClassJdbc(); // 准备插入数据 Student addStu1 = new Student(4, "李三", "2017-09-01", 96); Student addStu2 = new Student(5, "王四", "2018-09-01", 97); Student addStu3 = new Student(6, "长武", "2019-09-01", 98); // 插入默认数据 int result1 = jdbc.addStu(addStu1); System.out.println(result1 > 0 ? "语句1插入成功" : "语句1插入失败"); int result2 = jdbc.addStu(addStu2); System.out.println(result2 > 0 ? "语句1插入成功" : "语句1插入失败"); int result3 = jdbc.addStu(addStu3); System.out.println(result3 > 0 ? "语句1插入成功" : "语句1插入失败"); // 删除id为1的数据 int deleteResult1 = jdbc.deleteStu(1); System.out.println(deleteResult1 > 0 ? "id为1的数据删除成功" : "id为1的数据删除失败(可能是因为id为1的数据不存在)"); // 显示所有记录 List<Student> stuAll = jdbc.getStuAll(); if (stuAll != null) { System.out.println("此时数据库的全部数据为"); for (Student t : stuAll) { System.out.println(t); } } else { System.out.println("此时数据库没有数据"); } // 修改id=2的数据 Student updataStu = new Student(); updataStu.setName("山东理工"); updataStu.setId(2); int updataResult1 = jdbc.updateStu(updataStu); System.out.println(updataResult1 > 0 ? "修改id为2的数据成功" : "修改id为2的数据失败(可能是因为id为2的数据不存在)"); // 查询表中id=3的记录并显示 Student selectStu = jdbc.getStu(3); if (selectStu.getId() != -1) { System.out.println("id为3的数据为:" + selectStu); } else { System.out.println("没有查询到id=3的数据"); } } }
面向对象JDBC升级改造
将con封装成父类
package cn.sdut.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import com.mysql.jdbc.PreparedStatement; public class BaseDao { protected Connection con; protected PreparedStatement pst; protected ResultSet rs; //获得数据库的链接 public Connection getConnection() throws SQLException, ClassNotFoundException { // 加载JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); // 获取数据库的链接 Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/book", "root", "usbw"); return con; } //关闭对象 public void closeAll() throws SQLException { if(rs!=null) { rs.close(); } if(pst!=null) { pst.close(); } if(con!=null) { con.close(); } } }
面向接口编程是把客户的业务功能提取出来,作为接口。业务的具体实现通过该接口的实现类来完成。当客户需求变化时,只需编写该业务逻辑的新的实现类,或者通过更改配置文件中该接口的实现类就可以完成需求,不需要改写现有代码,减少对系统的影响。采用面向接口编程的好处包括:业务逻辑清晰、代码易懂、降低了程序的耦合性、方便扩展、可维护性强。
子类记得继承
public class StudentDao extends BaseDao{
将方法封装成接口
package cn.sdut.dao; import java.sql.SQLException; import java.util.List; import cn.sdut.po.*; public interface StudentDaoInterface { public int addStudent (Student student) throws ClassNotFoundException, SQLException ; public int delStudent (int id) throws ClassNotFoundException, SQLException; public int updataStudent(Student student) throws SQLException, ClassNotFoundException; public List<Student> getStudent () throws SQLException, ClassNotFoundException; public Student getStudentById(int id) throws SQLException, ClassNotFoundException; }
注意引入实现方法
public class StudentDao extends BaseDao implements StudentDaoInterface{
三层架构
访问层/界面层(用户与程序的交互)
^
||
业务逻辑层(判断数据的合法性)
^
||
数据库访问层(访问数据库)
界面层
package cn.sdut.aview; import java.util.Scanner; import java.util.List; import cn.sdut.base.BookBiz; import cn.sdut.po.Book; public class Main { public static void main(String[] args) { Scanner sc=new Scanner(System.in); String name =sc.next(); double price=sc.nextDouble(); int count=sc.nextInt(); BookBiz biz=new BookBiz(); Book addbook=new Book(1,name,price,count);//id为 系统自动赋值,故随意输入 try { int reulst=biz.addBook(addbook); List<Book> booklist=biz.selectAll(); for(Book b:booklist) { System.out.println(b); } } catch (Exception e) { // TODO: handle exception //e.printStackTrace(); System.out.println("dadsdsdsa"); } sc.close(); } }
业务逻辑层
package cn.sdut.base; import java.sql.SQLException; import java.util.List; import cn.sdut.dao.BookDao; import cn.sdut.po.Book; public class BookBiz { BookDao bookDao = new BookDao(); public int addBook(Book book) throws SQLException { int result = 0; if (book.getPrice() > 0 && book.getCount() > 0) { result = bookDao.addBook(book); } return result; } //和用户无关,故只需过度一下 public List<Book> selectAll() throws SQLException { return bookDao.selectAll(); } }
数据访问层
上面JDBC便是。
事务
定义:
指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
特性
- 原子性(atomicity) 一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
- 一致性(consistency) 事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation) 一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability) 持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
实现方法
在JDBC中,通过Connection对象进行事务管理,默认是自动提交事务。
如果人工设计事务需要:
-
手工将自动提交关闭(con.setAutoCommit(false); ),
-
通过commit方法进行提交,
-
rollback方法进行回滚,如果不提交,则数据不会真正的插入到数据库中。
public boolean transactionTset (Student student ,int id) throws ClassNotFoundException, SQLException { con=getConnection(); con.setAutoCommit(false); //设置SQL的非自动提交,并开启事务 //不会自动提交,而是进入缓冲区 //增加一个学生 String sql1= "insert into student values(null,?,?)"; pst=(PreparedStatement) con.prepareStatement(sql1); pst.setString(1, student.getName()) ; pst.setInt(2, student.getAge()); int resutl1=pst.executeUpdate(); //删除一个学生 String sql="updade student set name?,age=?,where id=?"; pst=(PreparedStatement) con.prepareStatement(sql); pst.setString(1, student.getName()); pst.setInt(2, student.getAge()); pst.setInt(3, student.getId()); int result2=pst.executeUpdate(); int result=resutl1*result2; if(result==1) { con.commit();//提交事务 return true; } else { con.rollback();//回滚事务 return false; } }
```java public void testtransactionTset() throws ClassNotFoundException, SQLException { Student stu=new Student(); stu.setName("fs"); stu.setAge(1); stu.setId(11); int id=11; boolean result=dao.transactionTset (stu ,id); assertEquals(result, true); //断言他是对的 }
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/15615832.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步