JDBC学习笔记(四)
减少各个Dao类间的重复代码,有以下几种方式:
写一个DBConnectionManager,将公共的查询逻辑做成方法,将sql语句作为参数传递给方法。
public class DBConnectionManager{
static{
Class.forName("com.mysql.jdbc.Driver");
}
//读操作
public static List<Map<String,Object>> selectObject(String sql, String[] params) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Map<String,Object>>> result = new ArrayList<Map<String,Object>>>();
try {
conn = DBConnectionManager.getConnection();
pstmt = conn.prepareStatement(sql);
for (int i = 0; params != null && i < params.length; i++) {
pstmt.setString(i + 1, params[i]);
}
rs = pstmt.executeQuery();
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
Map<String,Object> columnValue = new HashMap<String,Object>
int size = meta.getColumnCount();
for (int i = 1; i <= size; i++) {
String columnName = meta.getColumnLabel(i); //getColumnName返回的是数据库列名,getColumnLabel如有别名将返回列的别名,否则和getColumnName相同
columnValue.add(columnName,rs.getObject(columnName));
}
result.add(columnValue);
}
return result;
} catch (Exception e) {
//logger.info("Execute sql : " + sql + " fail!!!");
throw e;
} finally {
DBConnectionManager.free(conn, pstmt, rs);
}
}
//增删改操作
public static void updateObject(String sql, String[] params) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBConnectionManager.getConnection();
pstmt = conn.prepareStatement(sql);
for (int i = 0; params != null && i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
rs = pstmt.executeUpdate();
} catch (Exception e) {
//logger.info("Execute sql : " + sql + " fail!!!");
throw e;
} finally {
DBConnectionManager.free(conn, pstmt, rs);
}
}
//更好的做法是从数据库连接池中取链接
public static Connection getConnection(){
String dbName = "nnm5";
String passwrod = "OSSDB123";
String userName = "root";
String url = "jdbc:mysql://localhost:13306/" + dbName;
Connection conn = DriverManager.getConnection(url, userName,passwrod);
return conn;
}
public static void free(Connection conn,PreparedStatement pstmt,ResultSet rs){
if (rs != null) {
try {
rs.close();
} finally{
if(ps != null){
try{
ps.close();
}finally{
if(conn != null){
conn.close();
}
}
}
}
}
}
上述方法不好的地方在于返回的结果是 List<Map<String,Object>>,如果希望能像ORM框架那样的返回对象,就可以实现一个RowMapper,类似于Spring中提供的SimpleJdbcTemplate。
代码中加上RowMapper也有两种方式,第一种是使用模板方式,第二种是使用策略方式。
使用模板方式的例子如下,修改上面的模板类中的方法:
public static List selectObject(String sql, String[] params) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Map<String,Object>>> result = new ArrayList<Map<String,Object>>>();
try {
conn = DBConnectionManager.getConnection();
pstmt = conn.prepareStatement(sql);
for (int i = 0; params != null && i < params.length; i++) {
pstmt.setString(i + 1, params[i]);
}
rs = pstmt.executeQuery();
List list = new ArrayList();
int index=0;
while (rs.next()) {
list.add(objectMapper(rs)); //传递的是每次减去一行后的结果集
index++;
}
return list ;
} catch (Exception e) {
//logger.info("Execute sql : " + sql + " fail!!!");
throw e;
} finally {
DBConnectionManager.free(conn, pstmt, rs);
}
}
public abstract Object objectMapper(ResultSet rs);
具体的Dao中的代码如下:
public List getPerson(Integer id){
String sql="select id,name from person where id<?";
Object [] objs=new Object[]{id};
return super.getObject(sql,objs); //实际调用的还是该类中的objectMapper。
}
public Object objectMapper(ResultSet rs){
Person person=new Person;
try{
person.setId((Integer)rs.getObject(1));
person.setName((String)rs.getObject(2));
}catch(Exception e){
logger.log(e.printStackTrace());
}
return person;
}
使用策略模式修改模板类中的代码如下:
首先需要一个接口:
public interface RowMapper {
public Object objectMapper(ResultSet rs);
}
再修改模板类:
public static List selectObject(String sql, String[] params, RowMapper mapper) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Map<String,Object>>> result = new ArrayList<Map<String,Object>>>();
try {
conn = DBConnectionManager.getConnection();
pstmt = conn.prepareStatement(sql);
for (int i = 0; params != null && i < params.length; i++) {
pstmt.setString(i + 1, params[i]);
}
rs = pstmt.executeQuery();
List list = new ArrayList();
int index=0;
while (rs.next()) {
list.add(mapper.objectMapper(rs)); //传递的是每次减去一行后的结果集
index++;
}
return list ;
} catch (Exception e) {
//logger.info("Execute sql : " + sql + " fail!!!");
throw e;
} finally {
DBConnectionManager.free(conn, pstmt, rs);
}
}
具体的Dao中的代码:
public List getPerson(Integer id) {
String sql="select id,name from person where id<?";
Object [] objs=new Object[]{id};
return mu.getObject(sql,objs,new MyRowMapper1());
}
class MyRowMapper1 implements RowMapper{
public Object objectMapper(ResultSet rs) {
Person person=new Person();
try{
person.setId((Integer)rs.getObject(1));
person.setName((String)rs.getObject(2));
}catch(Exception e){
logger.log(e.printStackTrace());
}
return person;
}
}
使用JDBC的SimpleJDBCTemplate的代码:
String sql2 = "select id,tname as name,tpwd as password from tadd where tname = :tname";
RowMapper<UserBean> rw = new RowMapper<UserBean>(){
@Override
public UserBean mapRow(ResultSet paramResultSet, int paramInt)
throws SQLException {
UserBean ub = new UserBean();
ub.setId(paramResultSet.getObject("id") + "");
ub.setName(paramResultSet.getObject("tname") + "");
ub.setPassword(paramResultSet.getObject("tpwd") + "");
return ub;
}
};
Map<String, String> map = new HashMap<String, String>();
map.put("tname", "p");
UserBean ub = jdbctemplate.queryForObject(sql2, map, rw); //UserBean ub = jdbctemplate.queryForObject(sql2, map, new BeanPropertyRowMapper(UserBean.class));
System.out.println(ub.getName() + "," + ub.getPassword());
queryForObject只返回一条记录,如果是多条记录应该用query方法。queryForString(String sql,String.class)将返回字符串型的结果。如果没有对应的javabean,可以用queryForMap和queryForList方法。queryForMap返回一条记录,queryForList返回多条记录。
如果希望能够取得插入记录的主键值,可以调用回调函数,也可以在回调函数中对connection做更多的处理。
static Integer id=0;
public static int getId(final Person person) {
JdbcTemplate jdbcTemplate=new JdbcTemplate(JDBCUtils.getDataSource());
jdbcTemplate.execute(new ConnectionCallback(){
//传递的参数为Connection conn,自己可以在conn内写希望完成的功能
public Object doInConnection(Connection conn) throws SQLException,DataAccessException{
String sql="insert into person(name) values (?)";
PreparedStatement ps=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//返回所插入数据的主键
for(int i=0;i<10;i++){
ps.setString(1, person.getName());
ps.addBatch(); //批处理,将SQL语句进行打包
}
//ps.executeUpdate();
ps.executeBatch(); //没有这一行是不会插入数据的
ResultSet rs=ps.getGeneratedKeys();
while(rs.next())
id=rs.getInt(1);
return id;
}
});
return id;
}
SimpleJdbcTemplate里面封装了NamedJdbcTemplate,NamedJdbcTemplate里面又包含JdbcTemplate,增加了对泛型和可变长度参数的支持。从Spring 3.1开始,JdbcTemplate和NamedParameterJdbcTemplate提供了SimpleJdbcTemplate的功能。SimpleJdbcTemplate被标注为过时,使用JdbcTemplate和NamedParameterJdbcTemplate即可。
使用JDBCTemplate的KeyHolder获取新插入数据的主键:
String sql="insert into person(name) values (:name)";
Map map = new HashMap();
map.put(":tname","add");
//Person p = new Person();
//SqlParamterSource ps = new BeanPropertySqlParamterSource(p);
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbctemplate.update(sql, map, keyHolder );
int id = keyHolder.getKey().intValue(); //单主键的情况 Map map = keyHolder.getKeys(); //混合主键的情况
如果想调用NamedJdbcTemplate中的方法,可以使用jdbctemplate.getNamedJdbcTemplate()。
使用SimpleJdbcTemplate的例子:
@Override
public void delete(int id) {
String sql = "delete from user where id=?";
getSimpleJdbcTemplate().update(sql, id); } @Override
public User findById(int id) {
String sql = "select * from user where id=?";
return getSimpleJdbcTemplate().queryForObject(sql,
ParameterizedBeanPropertyRowMapper.newInstance(User.class), id); // 下面的方法只能返回一列,所以行不通
// return getSimpleJdbcTemplate().queryForObject(sql, User.class, id); } @Override
public int findByName(String name){
String sql = "select id from user where name=?";
return getSimpleJdbcTemplate().queryForObject(sql, Integer.class, name);
// Integer.class 改成int.class 不行
// 貌似只能用包装类 } @Override
public List<User> findAll() {
String sql = "select * from user";
return getSimpleJdbcTemplate().query(sql,
ParameterizedBeanPropertyRowMapper.newInstance(User.class));
} @Override
public int count() {
String sql = "select count(*) from user";
return getSimpleJdbcTemplate().queryForInt(sql);
} @Override
public void batchInsert(List<User> users) {
String sql = "insert into user(id,name)values(?,?)";
List<Object[]> parameters = new ArrayList<Object[]>();
for (User u : users) {
parameters.add(new Object[] { u.getId(), u.getName() });
}
getSimpleJdbcTemplate().batchUpdate(sql, parameters); }
JDBC学习笔记(四)的更多相关文章
- JDBC 学习笔记(十一)—— JDBC 的事务支持
1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...
- JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架
1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...
- JDBC学习笔记一
JDBC学习笔记一 JDBC全称 Java Database Connectivity,即数据库连接,它是一种可以执行SQL语句的Java API. ODBC全称 Open Database Conn ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- IOS学习笔记(四)之UITextField和UITextView控件学习
IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(四) indigo devices
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- ES6学习笔记<四> default、rest、Multi-line Strings
default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...
随机推荐
- mui 区域三级联动
<link href="../../css/mui.picker.css" rel="stylesheet" /><link href=&qu ...
- Nginx安装手册
前提是搭建yum安装环境,见前面的教程资料 Nginx安装手册1 nginx安装环境 nginx是C语言开发,建议在linux上运行,本教程使用Centos6.5作为安装环境. gcc 安装ngin ...
- 【转自知乎】:localhost、127.0.0.1 和 本机IP 三者的区别?
作者:知乎用户链接:https://www.zhihu.com/question/23940717/answer/26230963来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- jquery1.8 在IE8 下面报错:对象不支持此属性或方法 return b.getAttribute("id")===a
jquery1.8 在IE8 下面报错: 对象不支持此属性或方法 调试发现是下面这一行报错: 在IE8下面报错,在chrome和firefox都是好的. 实在找不到原因,最后把源码改成下面这样: 没有 ...
- spring boot容器启动详解
目录 一.前言 二.容器启动 三.总结 =======正文分割线====== 一.前言 spring cloud大行其道的当下,如果不了解基本原理那么是很纠结的(看见的都是约定大于配置,但是原理呢?为 ...
- setTimeout()方法,你真的懂吗?
今天在群里看到了一道经典的javascript题型,之前也遇到过,可是再次遇到时,还是做错,还是不理解,因此这里来做个笔记吧! 不说了,直接上代码吧 for(var i=1; i<=9; i++ ...
- jQuery:图片自动变换
<script type="text/javascript"> var aa=0; //设置变换时间为2s var timeChange=2000; //定义数组 va ...
- 解析MYsql explain执行计划extra列输出
EXPLAIN Extra 列信息: explain Extra列输出包含了关于mysql如何解决query的额外信息,特别是出现Using filesort 和 using temporary时,应 ...
- CSS基础--常用样式
一.背景相关 背景颜色 background-color :颜色名称/rgb值/十六进制值 背景图片 background-image :url('') 背景图片平铺方式 background-rep ...
- ETL工具--kettle篇(17.10.09更新)
ETL是EXTRACT(抽取).TRANSFORM(转换).LOAD(加载)的简称,实现数据从多个异构数据源加载到数据库或其他目标地址,是数据仓库建设和维护中的重要一环也是工作量较大的一块.当前知道的 ...