MyBatis第一课:回忆JDBC
来源:互联网 发布:生姜怎样治疗脱发 知乎 编辑:程序博客网 时间:2024/06/03 09:36
学完SSM很久了,一直想总结一下学到的东西,今天就先写一篇关于JDBC的,作为MyBatis的祭品。
在学习MyBatis之前,我们肯定都用过原生JDBC,不管是MyBatis还是Hibernate,这些ORM框架都是在JDBC的基础之上而进行封装的,我自己就曾经封装过一个JDBCTemplate,不过 功能就差远了。
因此我们先回顾一下原生JDBC:
首先是JDBC的操作步骤,大致如下:
1.加载驱动。
2.配置数据源,创建并获得一条与数据库的连接。
3.创建一个Statement对象。对于MySQL来说,常用的Statement有两种:执行静态语句的Statement和执行动态语句的PrepareStatement。
4.执行sql语句。Statement接口提供了三种执行sql语句的方式:execute(),excuteQuery() 查询,executeUpdate() 增删改 。 参考:三种执行方式的不同
5.操作结果集 。如果执行的是查询操作,则返回查询的结果集;如果执行的是更新(增删改)操作,则返回执行sql语句之后所影响的行数。
6.关闭连接,释放资源。
其中1,2两步我们可以封装在DBUtils中,这个网上随便都能搜到。3456步可以根据自己的方式尽量精简,比如把增删改都是为一种对数据库的更新操作,除了sql语句的不同以及预编译占位符需要填入的参数的不同,增删改确实可以整合在一起。
而查询操作就和更新不同,查询需要resultset来操作结果集,通过获得的resultset取出查询到的结果。
此时遇到一个问题,对于增删改操作,比如方法名就叫update(String sql, Object[] args),进行Statement的操作完成之后,我们可以直接在update方法内关闭连接。
但是,对于查询操作,比如方法名就叫query(String sql, Object[] args),进行查询之后可是要通过resultset来取得结果的,如果你直接把ResultSet作为参数返回,那么又如何获取到当时建立连接时创建的Connection并且关闭呢?那如果我们直接把操作结果集的实体类对象(比如:User对象,Student对象,他们的属性并不相同)作为参数传入query,又怎么动态的改变实体类对象呢?你却是可以动态的改变传入的sql语句来改变你要获取到的结果集,可是你又怎么用User对象/Student对象动态的把结果集设置为他们的属性值并且返回呢?当然,你可以通过更进一步的封装,我有以下几个思路:
1.保持实体类和数据库中字段值的高度一致,通过你查询的列名,用反射的方式,分别设置对象的属性
2.通过异步回调的方式,在update方法中调用回调函数,动态设置对象的属性。
3.......
第一种方法有点麻烦,因此我的解决方法如下:创建回调接口ResultSetHandler,利用回调函数的方式动态创建操作结果集的实体类对象,然后把实体类对象返回即可。
首先是DBUtils:
public class DBUtils {
private static String URL;
private static String username;
private static String password;
private static String driver;
static{
//获取配置文件信息
ResourceBundle res = ResourceBundle.getBundle("com.java.dbutils.jdbc-config");
URL = res.getString("jdbc-URL");
username = res.getString("jdbc-userName");
password = res.getString("jdbc-password");
driver = res.getString("jdbc-Driver");
try {
//加载驱动
Class.forName(driver);
System.out.println("加载驱动成功");
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
System.out.println("加载驱动失败");
}
}
public static Connection getConnection(){
//获取连接
Connection conn = null;
try {
conn = DriverManager.getConnection(URL,username,password);
System.out.println("获取连接成功");
} catch (SQLException e) {
// TODO 自动生成的 catch 块
System.out.println("获取连接失败");
e.printStackTrace();
}
return conn;
}
public static PreparedStatement getPreparedStatement(String sql){
PreparedStatement ppst = null;
try {
ppst = getConnection().prepareStatement(sql);
System.out.println("预编译成功");
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
System.out.println("预编译失败");
}
return ppst;
}
public static void closeALL(Connection conn,PreparedStatement ppst,ResultSet res){
try {
if(conn != null) conn.close();
if(ppst != null) ppst.close();
if(res != null) res.close();
System.out.println("关闭成功");
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
System.out.println("关闭失败");
}
}
public static void main(String[] args) {
}
}
JDBCTemplate:
public class jdbcTamplete {
@SuppressWarnings("finally")
public int update(String sql,Object...args){
Connection conn = null;
PreparedStatement ppst = null;
conn = DBUtils.getConnection();
int count = 0;
try {
ppst = conn.prepareStatement(sql);
for(int i=0;i<args.length;i++){
ppst.setObject(i+1, args[i]);
}
count = ppst.executeUpdate();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
System.out.println("更新失败");
}finally{
DBUtils.closeALL(conn, ppst, null);
System.out.println("关闭成功");
return count;
}
}
@SuppressWarnings("finally")
public Object query(String sql,ResultSetHandler rshd,Object... args){
Object object = null;
Connection conn = null;
PreparedStatement ppst = null;
ResultSet res = null;
try {
conn = DBUtils.getConnection();
//ppst = conn.prepareStatement("select * where ths_id = 2014051044");
ppst = conn.prepareStatement(sql);
if(args != null){
for(int i=0;i<args.length;i++){
ppst.setObject(i+1, args[i]);
}
}
res = ppst.executeQuery();
object = rshd.doHandler(res);
if(object == null){
System.out.println("null");
}
System.out.println("查询成功");
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
System.out.println("查询失败");
}finally {
DBUtils.closeALL(conn, ppst, res);
return object;
}
}
}
ResultSetHandler:
public interface ResultSetHandler {
public Object doHandler(ResultSet res) throws SQLException;
}
使用案例,查询所有部门信息:
@Override
public List<Department> queryDepartmentAll() {
// TODO 自动生成的方法存根
List<Department> deps = null;
String sql = "select * from department_test";
deps = (List<Department>) jdbcTamplete.query(sql, new ResultSetHandler() {
List<Department> departments = new ArrayList<>();
@Override
public Object doHandler(ResultSet res) throws SQLException {
// TODO 自动生成的方法存根
while(res.next()){
Department department = new Department();
department.setDpmt_Name(res.getString(1));
department.setThs_ID(res.getInt(2));
department.setThs_Name(res.getString(3));
department.setThs_Sex(res.getString(4));
department.setThs_Work(res.getInt(5));
department.setThs_shWork(res.getInt(6));
departments.add(department);
//System.out.println(res.getInt(2));
}
return departments;
}
}, null);
return deps;
}
当然,如果你觉得脑子不够用了,也可以利用jdk1.7的新特性,try with resources,可以把资源声明在try之后的括号中,在try执行结束之后,资源会自动释放。(PS:其实我经常这样用,写个简单的CURD还是美滋滋)
举个例子:
User bean = null;
String sql = "select * from User where name = ?";
try (Connection c = DBUtil.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, name);
ResultSet rs =ps.executeQuery();
if (rs.next()) {
bean = new User();
int id = rs.getInt("id");
bean.setName(name);
String password = rs.getString("password");
bean.setPassword(password);
bean.setId(id);
}
} catch (SQLException e) {
e.printStackTrace();
}
return bean;
}
- MyBatis第一课:回忆JDBC
- 回忆第一期
- Mybatis第一课-牛
- 学习mybatis 第一课
- Mybatis第一课
- 华为机试再回忆--第一题
- Mybatis-Mybatis、JDBC、Hibernate
- 我的第一条,一些回忆
- 【mybatis】mybatis JDBC事务细节
- Jdbc&Hibernate&MyBatis&IBatis
- 从jdbc到mybatis
- mybatis JDBC类型
- Mybatis事务管理-jdbc事务
- JDBC 与 MyBatis
- Mybatis常用jdbc类型
- hibernate jdbc mybatis 区别
- JDBC JDBCTemplate Mybatis Hibernate
- Mybatis 与 JDBC 比较
- 收集一些学习网站(有待更新)
- react打包模块--package--原理及源码解析
- pymysql语法记录
- 树链剖分+数据结构维护 Hdu 3966 Aragorn's Story 题解
- For Markdown
- MyBatis第一课:回忆JDBC
- 20170702Windows10_07_线程优先级及CPU亲和度
- 零碎知识点整理
- HDU5934-Bomb
- For markdown
- 常用布局
- 常见的几种Sort排序算法
- 学渣眼中的软件工程(三)
- zeroc-ice的全双工通信策略