目前在项目中基本上都是使用 Mybatis、Hibernate等ORM框架来作为数据连接层,都忘了JDBC的存在,这里就是记录一下如何使用JDBC 直接与数据库打交道。
这里的示例代码都是在现有项目中进行的,项目使用maven+spring +mybatis 架构。
插入操作
下面是示例代码:
private final static String getId = " select SEQ_ACTIVITY_CONF_ID.NEXTVAL FROM dual "; private final static String addSql = " insert into t_activity_conf ( " + "ACT_ID, ACT_NAME, QUY_SQL, DEL_FLAG, REC_GEN_TIME, REC_UPD_TIME, " + "REC_GEN_USER, REC_UPD_USER) values (?, ?, ?, ?, ?, ?, ?, ? )";public void add(ActivityConfigVo vo) { //1.直接获取已经配置好的数据源(本项目是 DruidDataSource) DataSource dataSource = SpringContextUtil.getBean(DataSource.class); //2.获取数据库连接和预处理语句(这里用JDK7的TWR特性,省去关闭资源的代码) try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(addSql); PreparedStatement ps2 = conn.prepareStatement(getId) ResultSet rs = ps2.executeQuery()){ //3.封装参数 //这里注意结果集和ps参数的下标都是从 1 开始的 if (rs.next()){ vo.setActId(rs.getLong(1)); } ps.setLong(1, vo.getActId()); ps.setNString(2, "测试活动"); //使用 setObject 方法会自动识别类型 ps.setObject(3, "select 1 from dual"); ps.setObject(4, "0"); //这里注意java.sql.Date 与 oracle 数据库 date的区别 ps.setTimestamp(5, new Timestamp(new java.util.Date().getTime())); ps.setObject(6, null); ps.setObject(7, vo.getRecGenUser()); ps.setObject(8, null); //4.执行sql ps.execute(); }catch (Exception e){ System.out.println("插入数据异常了"); e.printStackTrace(); } }@Test public void testAdd(){ ActivityConfigVo vo = new ActivityConfigVo(); vo.setActName("测试活动"); vo.setQuySql("select 1 from dual"); vo.setDelFlag("0"); vo.setRecGenUser(111L); activityConfigService.add(vo); }
查询操作
资源的获取还是使用TWR方式,主要是结果集赋值要注意。
private final static String selAllSql = " select * from t_activity_conf ";//如果表的列较多只查需要的列更好一些public List<ActivityConfigDto> selAll() { DataSource dataSource = SpringContextUtil.getBean(DataSource.class); List<ActivityConfigDto> list = new ArrayList<>(); try (Connection conn = dataSource.getConnection(); PreparedStatement ps=conn.prepareStatement(selAllSql); ResultSet rs = ps.executeQuery()){ if (rs.next()){ ActivityConfigDto dto = new ActivityConfigDto(); dto.setActId(rs.getLong("ACT_ID"));//使用数据表列名获取,也可以先统一处理别名,用别名获取 dto.setActName(rs.getString(2));//使用下标获取 dto.setQuySql(rs.getString(3)); dto.setDelFlag(rs.getString(4)); dto.setRecGenTime(new Date(rs.getTimestamp(5).getTime())); dto.setRecUpdTime(rs.getTimestamp(6) == null ? null : new Date(rs.getTimestamp(6).getTime())); dto.setRecGenUser(rs.getLong(7)); dto.setRecGenUser(rs.getLong(8)); list.add(dto); } }catch (Exception e){ System.out.println("查询出错了"); e.printStackTrace(); } return list; }@Test public void testSelAll(){ List<ActivityConfigDto> list = activityConfigService.selAll(); for (ActivityConfigDto dto : list){ System.out.println(dto.toString()); } }
更新操作
//这里也可以写成通用的,但是修改前要先查询出对应的记录,只需关心要修改的字段 private final static String updateByIdSql = " update t_activity_conf set " + " ACT_NAME = ?, QUY_SQL = ?, REC_UPD_TIME = sysdate, " + " REC_UPD_USER = ? where ACT_ID = ?";public int updateById(ActivityConfigVo vo) { DataSource dataSource = SpringContextUtil.getBean(DataSource.class); int rs = 0; try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(updateByIdSql)){ ps.setNString(1, vo.getActName()); ps.setObject(2, vo.getQuySql()); ps.setObject(3, vo.getRecUpdUser()); ps.setObject(4, vo.getActId()); rs = ps.executeUpdate(); }catch (Exception e){ System.out.println("更新数据异常了"); e.printStackTrace(); } return rs; }@Test public void testUpdateById(){ ActivityConfigVo vo = new ActivityConfigVo(); vo.setActId(14L); vo.setActName("测试活动更新"); vo.setQuySql("select 2 from dual"); vo.setRecUpdUser(122L); int updateRow = activityConfigService.updateById(vo); System.out.println(updateRow); }
删除操作
这个表设计时考虑是逻辑删除,如果是逻辑删除也就是个更新操作,可以用通用的sql也可以单独写sql,这里就做个物理删除的例子:
private final static String deleteByIdSql = "delete from dma.t_activity_conf " + " where ACT_ID = ?";public int deleteById(ActivityConfigVo vo) { DataSource dataSource = SpringContextUtil.getBean(DataSource.class); int rs = 0; try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(deleteByIdSql)){ ps.setObject(1, vo.getActId()); rs = ps.executeUpdate(); }catch (Exception e){ System.out.println("删除数据异常了"); e.printStackTrace(); } return rs; }@Test public void testDeleteById(){ ActivityConfigVo vo = new ActivityConfigVo(); vo.setActId(15L); int rs = activityConfigService.deleteById(vo); System.out.println(rs); }
无意间发现 execute() 与 executeUpdate() 不仅仅是返回值的区别,使用 execute() 数据删除了,但是返回结果为 false,使用 executeUpdate() 数据删除返回 1。
顺便看一下execute() 和 executeUpdate() 在接口 PreparedStatement 中的约定:
/** * 在此 PreparedStatement 对象中执行SQL语句,该对象可以是任何类型的SQL语句。 * 一些预语句返回多个结果; * execute 方法处理这些复杂的语句, * 由 executeQuery 和 executeUpdate 方法处理的更简单形式的语句。 * execute 方法返回一个 boolean 来指示第一个结果的形式。 * 您必须调用方法 getResultSet 或 getUpdateCount 来检索结果。 * 您必须调用 getMoreResults 才能移至任何后续结果。 * * @return 如果第一个结果是 ResultSet 对象,则为 true ; * 如果第一个结果是更新计数或没有结果,则为 false * @exception SQLException if a database access error occurs; * this method is called on a closed <code>PreparedStatement</code> * or an argument is supplied to this method * @throws SQLTimeoutException when the driver has determined that the * timeout value that was specified by the {@code setQueryTimeout} * method has been exceeded and has at least attempted to cancel * the currently running {@code Statement} * @see Statement#execute * @see Statement#getResultSet * @see Statement#getUpdateCount * @see Statement#getMoreResults */ boolean execute() throws SQLException;
/** * 在此 PreparedStatement 对象中执行SQL语句,该对象必须是SQL数据操作语言(DML)语句, * 例如 INSERT , UPDATE 或 DELETE ; * 或不返回任何内容的SQL语句,例如 DDL 语句。 * @return (1)返回SQL数据操作语言(DML)语句的行计数,或者(2)不返回任何内容SQL语句,返回 0 * @exception SQLException if a database access error occurs; * this method is called on a closed <code>PreparedStatement</code> * or the SQL statement returns a <code>ResultSet</code> object * @throws SQLTimeoutException when the driver has determined that the * timeout value that was specified by the {@code setQueryTimeout} * method has been exceeded and has at least attempted to cancel * the currently running {@code Statement} */ int executeUpdate() throws SQLException;
来源:oschina
链接:https://my.oschina.net/u/3488841/blog/4308968