JDBC 连接数据库示例

六眼飞鱼酱① 提交于 2020-08-08 09:40:07

        目前在项目中基本上都是使用 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;

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!