一、学习JDBC
1.什么是JDBC
JDBC的全称是Java数据库连接(Java Dalabase Connectivity),它是一套用于执行soL语句的Java API应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、更新、新增和删除的操作。
不同种类的数据库(如MySQL、Oracle 等)在其内部处理数据的方式是不同的。如果直接使用数据库厂商提供的访问接口操作数据库,应用程序的可移植性就会变得很差。例如,用户当前在程序中使用的是MySQL提供的接口操作数据库,如果换成Oracle数据库,则需要重新使用Oracle数据库提供的接口,这样代码的改动量会非常大。有了JDBC后,这种情况就不复存在了,因为它要求各个数据库厂商按照统一的规范来提供数据库驱动,而在程序中是由JDBC 和具体的数据库驱动联系,所以用户就不必直接与底层的数据库交互,这使得代码的通用性更强。
JDBC在应用程序与数据库之间起到了一个桥梁作用。当应用程序使用,JDBC访问特定的数据库时,需要通过不同数据库驱动与不同的数据库进行连接,连接后即可对该数据库进行相应的操作作。
在开发JDBC程序前,该包定义了一系列访问数据库的接口和关。常 用的API。JDBC API主要位于 java.sql包中,该包定义了一系列数据库的接口和类。
2.1 Driver 接口
Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。锅要注意的是,在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指MySQL驱动JAR包)。
2.2 DriverManager 类
DriverManager类用于加载JDBC驱动并且创建与数据库的连接。在DriverManager类中,定义了两个比较重要的静态方法。
2.3 Connection 接口
Connecion接按口代表Java程序和数据库的连接,只有获得该连接对象后才能访问数据库,并操作数据表。在Connection接口中,定义了一系列方法,其常用方法如下表所示:
2.4 Statement 接口
Statement接口用于执行静态的SQL语句,并返回一个结果对象,该接口的对象通过Connection实例的createStatement()方法获得。利用该对象把静态的SQL语句发送到数据库编译执行,然后返回数据库的处理结果。在Statement接口中,提供了3个常用的执行SQL语句的方法,具体如下表所示:
2.5 PreparedStatement 接口
Statement接口封装了JDBC执行SQL语句的方法,可以完成Java程序执行SQL语句的操作。然而,在实际开发过程中往往需要将程序中的变量作为SQL语句的查询条件,而使用Statement接口操作这些SQL语句会过于繁琐,并且存在安全方面的问题。针对这-问题,JDBCAPI提供了扩展的PreparedStatement接口。
ResultSet 接口中定义了大量的getXxx()方法,而采用哪种getXxx()方法取决于字段的数据类型。程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。例如,数据表的第1列字段名为id,字段类型为int,那么既可以使用getin(1)字段索引的方式获取该列的值,也可以使用gltln(id)字段名称的方式获取该列的值。
JDBC的使用可以按照以下几个步骤进行。
1.实现第一个JDBC程序
在MySQL中创建一个名称为jdbc的数据库,然后在该数据库中创建一个users表,创建数据库和表的SQL语句如下所示。
CREATE DATABASE jdbc; USE jdbc; CREATE TABLE users( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(40), password VARCHAR(40), email VARCHAR(60), birthday DATE )CHARACTER SET utf8 COLLATE utf8_general_ci;
数据库和表创建成功后,创建插入记录:
INSERT INTO users (NAME, PASSWORD, email, birthday) VALUES('zs', '123456','zs@sina.com','1980-12-04'); INSERT INTO users (NAME, PASSWORD, email,birthday) VALUES('lisi','123456','lisi0sina.com','1981-12-04'); INSERT INTO users (NAME, PASSWORD, email,birthday) VALUES('wangwu','123456','wangwu@sina.com','1979-12-04');
执行结果如图
2.编写JDBC程序
在项目chapter09的src目录下,新建一个名称为chapter02.jdbc.example的包,在该包中创建类Example01,该类用于读取数据库中的users表,并将结果输出到控制台
package chapter12.jdbc.example; import java.sql.Statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Date; public class example01 { public static void main(String[] args) throws SQLException{ Connection conn = null; Statement stmt = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC"; String username = "root"; String password = "123456"; conn = DriverManager.getConnection(url,username,password); stmt = conn.createStatement(); String sql = "select * from users"; rs = stmt.executeQuery(sql); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String psw = rs.getString("password"); String email = rs.getString("email"); Date birthday = rs.getDate("birthday"); System.out.println(id+" "+name+" "+email+" "+birthday); } }catch (ClassNotFoundException e) { // TODO: handle exception e.printStackTrace(); }finally { if(rs!=null) { try { rs.close(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); } rs=null; } if (stmt!=null) { try { stmt.close(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); } stmt=null; } if (conn!=null) { try { conn.close(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); } conn=null; } } } }
结果如图
PreparedStatement对象
在该类中使用PreparedStatement对象对数据库进行插入数据的操作
package chapter12.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class example02 { public static void main(String[] args) throws SQLException{ Connection conn = null; PreparedStatement preStmt = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC"; String username = "root"; String password = "123456"; conn = DriverManager.getConnection(url,username,password); String sql ="INSERT INTO users (NAME, PASSWORD, email,birthday)"+"VALUES(?,?,?,?)"; preStmt =conn.prepareStatement(sql); preStmt.setString(1, "zl"); preStmt.setString(2, "123456"); preStmt.setString(3, "zl@sina.com"); preStmt.setString(4, "1789-12-23"); preStmt.executeUpdate(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if(preStmt!=null) { try { preStmt.close(); } catch (SQLException e) { e.printStackTrace(); } preStmt = null; } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn=null; } } } }
查询结果如图
ResultSet对象
使用ResultSet对象取出指定数据的信息
package chapter12.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class example03 { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC"; String username = "root"; String password = "123456"; conn = DriverManager.getConnection(url,username,password); String sql = "select * from users"; stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery(sql); System.out.print("第2条数据的name值为:"); rs.absolute(2); System.out.println(rs.getNString("name")); System.out.print("第1条数据的name值为:"); rs.beforeFirst(); //将指针定位到结果集中第一行数据之前 rs.next(); //指针向后滚动 System.out.println(rs.getString("name")); System.out.print("第4条数据的name值为:"); rs.afterLast(); //将指针定位到结果集中最后一条数据之后 rs.previous(); //指针向前滚动 System.out.println(rs.getString("name")); } catch (Exception e) { e.printStackTrace(); } finally { if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn=null; } } } }
程序的运行结果如图
使用JDBC完成数据的增删改查
1.创建JavaBean
User类的具体实现方式如下
package chapter12.jdbc.example; import java.util.Date; public class user { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } private String username; private String password; private String email; private Date birthday; }
2.创建工具类
由于每次操作数据库时,都需要加载数据库驱动、建立数据库连接以及关闭数据库连接,为了避免代码的重复书写,下面建立一个专门用于数据库相关操作的工具类。在包中创建一个封装了上述操作的工具类JDBCUtils,JDBCUtils的具体实现方式如下
package chapter12.jdbc.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { public static Connection getConnection() throws SQLException,ClassNotFoundException{ Class.forName("com.mysql.cj.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password); return conn; } public static void release(Statement stmt, Connection conn) { if(stmt!=null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn=null; } } public static void release(ResultSet rs,Statement stmt,Connection conn) { if(rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } release(stmt, conn); } }
3.创建DAO
代码如下:
package chapter12.jdbc.example; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import chapter12.jdbc.example.user; import chapter12.jdbc.example.JDBCUtils; public class UsersDao { //添加用户的操作 public boolean insert(user user) { Connection conn = null; Statement stmt=null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); stmt = conn.createStatement(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String birthday = sdf.format(user.getBirthday()); String sql = "INSERT INTO users(id,name,password,email,birthday)"+ "VALUES(" +user.getId() +",'" +user.getUsername() +"','" +user.getPassword() +"','" +user.getEmail() +"','" +birthday + "')"; System.out.println(sql); int num = stmt.executeUpdate(sql); if (num > 0) { return true; } return false; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs,stmt,conn); } return false; } public ArrayList<user> findAll(){ Connection conn = null; Statement stmt=null; ResultSet rs = null; ArrayList<user> list = new ArrayList<user>(); try { conn = JDBCUtils.getConnection(); stmt = conn.createStatement(); String sql = "SELECT * FROM users"; rs = stmt.executeQuery(sql); while(rs.next()) { user user = new user(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("name")); user.setPassword(rs.getString("password")); user.setEmail(rs.getString("email")); user.setBirthday(rs.getDate("birthday")); list.add(user); } return list; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt, conn); } return null; } public user find(int id) { Connection conn=null; Statement stmt=null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); stmt=conn.createStatement(); String sql = "SELECT * FROM users WHERE id=" + id; rs = stmt.executeQuery(sql); while(rs.next()) { user user = new user(); user.setId(rs.getInt("id")); user.setUsername(rs.getString("name")); user.setPassword(rs.getString("password")); user.setEmail(rs.getString("email")); user.setBirthday(rs.getDate("birthday")); return user; } return null; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs,stmt, conn); } return null; } public boolean delete(int id) { Connection conn = null; Statement stmt = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); stmt= conn.createStatement(); String sql = "DELETE FROM users WHERE id=" + id; int num =stmt.executeUpdate(sql); if(num > 0) { return true; } return false; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(rs, stmt,conn); } return false; } public boolean update(user user) { Connection conn =null; Statement stmt = null; ResultSet rs = null; try { conn= JDBCUtils.getConnection(); stmt = conn.createStatement(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String birthday =sdf.format(user.getBirthday()); String sql = "UPDATE users set name='"+user.getUsername() +"',password='"+user.getPassword() + "',email='" +user.getEmail() + "',birthday='" + birthday +"'WHERE id=" + user.getId(); int num = stmt.executeUpdate(sql); if (num > 0) { return true; } return false; } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtils.release(rs, stmt, conn); } return false; } }
4.创建测试类
代码如下:
package chapter12.jdbc.example; import java.util.Date; import chapter12.jdbc.example.user; import chapter12.jdbc.example.JDBCUtils; public class JdbcInsertTest { public static void main(String[] args) { //向users表插入一个用户信息 UsersDao ud = new UsersDao(); user user=new user(); user.setId(5); user.setUsername("hl"); user.setPassword("123"); user.setEmail("hl@sina.com"); user.setBirthday(new Date()); boolean b= ud.insert(user); System.out.println(b); } }
结果如图
从查询结果可以看出,users表中添加了一条name为h1的数据,该数据正是文件 JdbclnsertTest.java中所插入的数据。
编写测试类FindAllUsersTest,该类用于实现读取users表中所有的数据:
package chapter12.jdbc.example; import java.util.ArrayList; public class FindAllUsersTest { public static void main(String[] args) { UsersDao usersDao = new UsersDao(); ArrayList<user> list = usersDao.findAll(); for (int i=0; i< list.size(); i++) { System.out.println("第" + (i+1) + "条数据的username的值为:" +list.get(i).getUsername()); } } }
结果如图:
编写测试类FindUserByldTest,在该类中实现读取 users表中指定的数据:
package chapter12.jdbc.example; import chapter12.jdbc.example.UsersDao; import chapter12.jdbc.example.user; public class FindUserByldTest { public static void main(String[] args) { UsersDao usersDao = new UsersDao(); user user = usersDao.find(1); System.out.println("id为1的User对象的name值为:"+user.getUsername()); } }
结果如图:
编写测试类UpdateUserTest,在该类中实现修改users表中数据的操作:
package chapter12.jdbc.example; import java.util.Date; import chapter12.jdbc.example.UsersDao; import chapter12.jdbc.example.user; public class UpdateUserTest { public static void main(String[] args) { UsersDao usersDao = new UsersDao(); user user = new user(); user.setId(4); user.setUsername("zhaoxiaoliu"); user.setPassword("456"); user.setEmail("zhaoxiaoliu@sina.com"); user.setBirthday(new Date()); boolean b=usersDao.update(user); System.out.println(b); } }
查询结果如图:
编写测试类DeleteUserTest,该类实现了删除users 表中数据的操作:
package chapter12.jdbc.example; import chapter12.jdbc.example.UsersDao; public class DeleteUserTest { public static void main(String[] args) { UsersDao usersDao = new UsersDao(); boolean b = usersDao.delete(4); System.out.println(b); } }
结果如图:
从上图中我们可以看出,users表中id为4的User对象已被成功删除了。所以,使用JDBC对数据库中数据进行增删改查的操作已经完成。