您的位置:首页 > 博客中心 > 数据库 >

JDBC学习笔记——增删改查

时间:2022-03-14 02:07

1、数据库准备                                                                                 

      要用JDBC操作数据库,第一步当然是建立数据表:

1 2 3 4 5 6 CREATE TABLE `user` (   `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,   `name` varchar(45) DEFAULT NULL,   `birthday` date DEFAULT NULL,   `money` double DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2、JDBC连接数据库的基本步骤                                                            

      JDBC连接数据库包含以下几个基本步骤:1、注册驱动 ;2、建立连接(Connection);3、创建SQL语句(Statement);4、执行语句;5、处理执行结果(ResultSet);6、释放资源。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static void test() throws SQLException{     // 1.注册驱动     Class.forName("com.mysql.jdbc.Driver");       // 2.建立连接  url格式 - JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…     Connection conn = DriverManager.getConnection("jdbc:", "root", "");       // 3.创建语句     Statement st = conn.createStatement();       // 4.执行语句     ResultSet rs = st.executeQuery("select * from user");       // 5.处理结果     while (rs.next()) {           System.out.println(rs.getObject(1) + "\t" + rs.getObject(2) + "\t" + rs.getObject(3) + "\t" + rs.getObject(4));     }       // 6.释放资源     rs.close();     st.close();     conn.close(); }

3、简单的增删改查                                                                        

      第二节的代码有一个问题,如果我们在执行代码时抛出异常,那么Connection就无法关闭了,所以我们应该把关闭资源操作放入finally中,这样就无论如何都会关闭这些数据库连接资源。同时我们还会扩展程序功能,上面的例子只是展示了一个查询操作,接下来将会展示最常用的增、删、改、查四个操作。首先介绍一个JdbcUtils类,该类会封装数据库连接步骤中的第一步、第二步及第六步操作,分别是注册驱动,建立连接及释放资源操作。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public final class JdbcUtils {     static {         try {             Class.forName("com.mysql.jdbc.Driver");         } catch (ClassNotFoundException e) {             throw new ExceptionInInitializerError(e);         }     }         private JdbcUtils() {     }       public static Connection getConnection() throws SQLException {         return DriverManager.getConnection("jdbc:", "root", "");     }       public static void free(ResultSet rs, Statement st, Connection conn) {         try {             if (rs != null)                 rs.close();         } catch (SQLException e) {             e.printStackTrace();         } finally {             try {                 if (st != null)                     st.close();             } catch (SQLException e) {                 e.printStackTrace();             } finally {                 if (conn != null)                     try {                         conn.close();                     } catch (SQLException e) {                         e.printStackTrace();                     }             }         }     } }

  可以看到,这个类的构造函数是一个私有构造函数,所以我们将无法创建这个类的实例。在静态初始化域,我们进行了注册驱动操作,静态初始化域只会在类加载的时候执行一次,这样可以保证只要加载了这个类,我们会且仅会注册一次驱动。然后getConnection()方法封装了建立连接操作,free(rs, st, conn)方法封装了释放资源操作。接下来可以看看如何使用JdbcUtils类进行增、删、改、查操作:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 //增加操作 void create() throws SQLException {     Connection conn = null;     Statement st = null;     ResultSet rs = null;     try {                 conn = JdbcUtils.getConnection();         st = conn.createStatement();         int i = st                 .executeUpdate("insert into user(name,birthday, money) values (‘name1‘, ‘1987-01-01‘, 400) ");         System.out.println("i=" + i);     } finally {         JdbcUtils.free(rs, st, conn);     } }   //删除操作 void delete() throws SQLException {     Connection conn = null;     Statement st = null;     ResultSet rs = null;     try {         conn = JdbcUtils.getConnection();         st = conn.createStatement();         int i = st.executeUpdate("delete from user where id>4");         System.out.println("i=" + i);     } finally {         JdbcUtils.free(rs, st, conn);     } }   //修改操作 void update() throws SQLException {     Connection conn = null;     Statement st = null;     ResultSet rs = null;     try {         conn = JdbcUtils.getConnection();         st = conn.createStatement();         int i = st.executeUpdate("update user set money=money+10 ");         System.out.println("i=" + i);     } finally {         JdbcUtils.free(rs, st, conn);     } }   //查询操作 void read() throws SQLException {     Connection conn = null;     Statement st = null;     ResultSet rs = null;     try {         conn = JdbcUtils.getConnection();         st = conn.createStatement();         rs = st.executeQuery("select id, name, money, birthday  from user");         while (rs.next()) {             System.out.println(rs.getObject("id") + "\t"                     + rs.getObject("name") + "\t"                     + rs.getObject("birthday") + "\t"                     + rs.getObject("money"));         }     } finally {         JdbcUtils.free(rs, st, conn);     } }  

4、面向对象封装增删改查                                                               

      第三节的例子只是为了展示如何使用JDBC进行增删改查操作,在项目中真正使用时,我们是不会像上面的例子这样简单使用的,Java是面向对象的,所以我们一般会使用面向对象的思想对操作进行封装。首先,其实对于数据表每一条数据,我们都可以认为它是一个对象实例,例如此例中我们定义的数据表User有id,name,birthday和money四个属性,对应的我们可以创建User类如下:

1 2 3 4 5 6 7 8 public class User {     private int id;     private String name;     private Date birthday;     private float money;              //getters and setters }

  按照"面向接口编程而非面向实现编程"的原则,我们可以定义数据表操作的接口如下:

1 2 3 4 5 6 public interface UserDao {     public void addUser(User user);     public User getUser(int userId);     public void update(User user);     public void delete(User user); }

      然后我们使用JDBC方式实现这个接口如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 public class UserDaoJdbcImpl implements UserDao {     public void addUser(User user) {         Connection conn = null;         PreparedStatement ps = null;         ResultSet rs = null;         try {             conn = JdbcUtils.getConnection();             String sql = "insert into user(name,birthday, money) values (?,?,?) ";             ps = conn.prepareStatement(sql);             ps.setString(1, user.getName());             ps.setDate(2, new java.sql.Date(user.getBirthday().getTime()));             ps.setFloat(3, user.getMoney());             ps.executeUpdate();         } catch (SQLException e) {             throw new RuntimeException(e.getMessage(), e);         } finally {             JdbcUtils.free(rs, ps, conn);         }     }       public void delete(User user) {         Connection conn = null;         Statement st = null;         ResultSet rs = null;         try {             conn = JdbcUtils.getConnection();             st = conn.createStatement();             String sql = "delete from user where id=" + user.getId();             st.executeUpdate(sql);         } catch (SQLException e) {             throw new RuntimeException(e.getMessage(), e);         } finally {             JdbcUtils.free(rs, st, conn);         }     }       public User getUser(int userId) {         Connection conn = null;         PreparedStatement ps = null;         ResultSet rs = null;         User user = null;         try {             conn = JdbcUtils.getConnection();             String sql = "select id, name, money, birthday  from user where id=?";             ps = conn.prepareStatement(sql);             ps.setInt(1, userId);             rs = ps.executeQuery();             while (rs.next()) {                 user = new User();                 user.setId(rs.getInt("id"));                 user.setName(rs.getString("name"));                 user.setMoney(rs.getFloat("money"));                 user.setBirthday(rs.getDate("birthday"));             }         } catch (SQLException e) {             throw new RuntimeException(e.getMessage(), e);         } finally {             JdbcUtils.free(rs, ps, conn);         }         return user;     }       public void update(User user) {         Connection conn = null;         PreparedStatement ps = null;         ResultSet rs = null;         try {             conn = JdbcUtils.getConnection();             String sql = "update user set name=?, birthday=?, money=? where id=? ";             ps = conn.prepareStatement(sql);             ps.setString(1, user.getName());             ps.setDate(2, new java.sql.Date(user.getBirthday().getTime()));             ps.setFloat(3, user.getMoney());             ps.setInt(4, user.getId());             ps.executeUpdate();         } catch (SQLException e) {             throw new RuntimeException(e.getMessage(), e);         } finally {             JdbcUtils.free(rs, ps, conn);         }     } }

  可以看到,真正核心的代码其实和第二节的代码很相像,但是按照这种风格写的代码扩展性更好,如果哪一天我们不打算使用JDBC,而改用Hibernate连接数据库,使用接口编程只需修改实现,不需要修改其他部分,大大减小了修改难度。

5、传入sql执行                                                                             

      需要说明的是,上面的代码使用了PreparedStatement对象,PrepareStatement是预编译的Statement对象,它在创建的时候就会把sql的大体框架搭建起来,把一些变量用占位符表示,使用时,我们再设置这些占位符的值。PrepareStatement最大的特点是可以防止sql注入,更安全,所以再需要拼接用户输入的场景,推荐使用PrepareStatement。

      第四节代码的编码风格类似Hibernate,Hibernate的很多操作都是需要传入对象的,但是这种传递对象的方式灵活性不高,例如update()方法,我们把User对象上的所有属性都更新了,但是可能我们只想更新birthday一个属性,更新其他属性有点多余,所以更好的方法应该是传入sql语句,而不是一个User对象。再仔细观察,我们发现,其实我们最终只是调用了Statement上的两个方法,分别是executeUpdate和executeQuery两个方法。所以我们可以把上面的增删改查修改为如下形式:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 public class UserDaoUtils {     private UserDaoUtils(){     }         static User executeQuery(String sql, Object[] params) throws SQLException {         Connection conn = null;         PreparedStatement ps = null;         ResultSet rs = null;         User user = null;         try {             conn = JdbcUtils.getConnection();             ps = conn.prepareStatement(sql);             for (int i = 1; i <= params.length; i++) {                 ps.setObject(i, params[i - 1]);             }               rs = ps.executeQuery();               while (rs.next()) {                 user = new User();                 user.setId(rs.getInt("id"));                 user.setBirthday(rs.getDate("birthday"));                 user.setMoney(rs.getFloat("money"));                 user.setName(rs.getString("name"));             }         } finally {             JdbcUtils.free(rs, ps, conn);         }         return user;     }         static int executeUpdate(String sql, Object[] params) throws SQLException {         Connection conn = null;         PreparedStatement ps = null;         int rs = 0;         try {             conn = JdbcUtils.getConnection();             ps = conn.prepareStatement(sql);             for (int i = 1; i <= params.length; i++) {                 ps.setObject(i, params[i - 1]);             }               rs = ps.executeUpdate();         } finally {             JdbcUtils.free(null, ps, conn);         }         return rs;     } }   public class UserDaoJdbcImpl2 implements UserDao{     @Override     public void addUser(User user) {         try {             UserDaoUtils.executeUpdate("insert into user(name,birthday, money) values (?,?,?)", new Object[]{user.getName(), user.getBirthday(), user.getMoney()});         } catch (SQLException e) {             e.printStackTrace();         }     }       @Override     public User getUser(int userId) {         User user = null;         try {             user = UserDaoUtils.executeQuery("select id, name, money, birthday  from user where id=?", new Object[]{userId});         } catch (SQLException e) {             e.printStackTrace();         }         return user;     }       @Override     public void update(User user) {         try {             UserDaoUtils.executeUpdate("update user set name=?, birthday=?, money=? where id=?", new Object[]{user.getName(), user.getBirthday(), user.getMoney(), user.getId()});         } catch (SQLException e) {             e.printStackTrace();         }     }       @Override     public void delete(User user) {         try {             UserDaoUtils.executeUpdate("delete from user where id=?", new Object[]{user.getId()});         } catch (SQLException e) {             e.printStackTrace();         }     } }

  首先我们定义了一个UserDaoUtils对象,该对象包含两个方法,分别是executeQuery()和executeUpdate()方法,这两个方法均包含两个参数,分别是sql语句及sql语句的参数。然后我们定义了UserDaoJdbcImpl2类,该类使用UserDaoUtils实现了UserDao接口,相较于UserDaoJdbcImpl简化了很多。

6、利用结果集元数据封装对象                                                          

      上面的UserDaoJdbcImpl2和UserDaoUtils的代码都已经很简洁了,但是有个问题,如果我们想封装其他对象的JDBC操作,那么我们将不得不重新定义一对Utils和Impl,这个其实是重复劳动,那么我们有没有什么方法可以避免这些重复劳动呢?Impl对象是必须定义的,因为我们需要实现不同的对象,如果想少定义一些对象,那么就只能不定义Utils对象。查看UserUtils的exectueQuery()和executeUpdate()方法,发现只有executeQuery()方法是与User对象耦合的,而且耦合部分只有封装结果集的部分,我们可以把这一部分代码抽象成一个接口,让调用方传入,这样就可以避免这部分耦合,所以定义接口如下:

1 2 3 public interface RowMapper {     public Object mapRow(ResultSet rs) throws SQLException; }

  然后我们修改第四节的UserDaoUtils对象如下,并重命名为MyJdbcTemplate:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public class MyJdbcTemplate {     private MyJdbcTemplate(){}         public static Object executeQuery(String sql, Object[] args, RowMapper rowMapper) {         Connection conn = null;         PreparedStatement ps = null;         ResultSet rs = null;         try {             conn = JdbcUtils.getConnection();             ps = conn.prepareStatement(sql);             for (int i = 0; i < args.length; i++)                 ps.setObject(i + 1, args[i]);             rs = ps.executeQuery();             Object obj = null;             if (rs.next()) {                 obj = rowMapper.mapRow(rs);             }             return obj;         } catch

热门排行

今日推荐

热门手游