JDBC API主要的功能
1.与数据库建立连接;
2.执行SQL语句;
3.处理结果。JDBC关键字的使用
1.DriverManager:依据数据库的不同,管理JDBC驱动;
2.Connection:负责连接数据库并且担任传送数据库的任务;
3.Statement:由Connection产生、负责执行SQL语句;
4.ResultSet:负责保存Statement执行后所产生的查询结果;
5.PreparedStatement接口(预编译的SQL语句)提高了SQL语句的性能、代码的安全性、代码的可读性和可维护性。
Statement常用方法:
ResultSet executeQuery(String sql):执行SQL查询并且获取ResultSet对象
Int executeUpdate(String sql):可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数
Boolean execute(String sql):可以执行任意SQL语句,然后获得一个布尔值,表示是否返回ResultSet
Boolean next():将光标从当前位置向下移动一行
Boolean previous():游标从当前位置向上移动一行
Void close():关闭ResultSet对象
Int getInt(int colIndex):以int形式获取结果集当前行指定列号值
Int getInt(String colLabel):以int形式获取结果集当前行指定的列名值
Float getFloat(int colIndex):以float形式获取结果集当前行指定列号值
Float getFloat(String colLabel):以float形式获取结果集当前指定列名值
String getString(int colIndex):以Sting形式获取当前行指定列号值
String getString(String colLabel):以String形式获取当前行指定列名值PreparedStatement比Statement提高了代码的可读性和可维护性,提高了SQL语句执行的性能,提高了安全性。
JDBC的操作步骤
1.加载JDBC驱动;
2.与数据库建立连接;
3.创建Statement或PreparedStatement对象;
4.发送SQL语句,并且得到返回结果;
5.处理返回结果;
6.释放资源。遍历结果集中数据可使用列号或者列名标识列。
数据访问层 - DAO模式
持久化是将程序中的数据在瞬时状态下和持久状态间转换的机制。
持久化的主要操作:读取、查找、保存、修改、删除。
DAO(Data Access Object):数据存取对象,位于业务逻辑和持久化数据之间,能够实现对持久化数据的访问。
DAO在实体类与数据库之间起着转换器的作用,能够把实体类转换为数据库中的记录。
DAO模式是作用
1.隔离业务逻辑代码和数据访问代码;
2.隔离不同数据库的实现。DAO模式的组成部分
1.DAO接口;
2.DAO实现类;
3.实体类;
4.数据库连接和关闭工具类。分层开发
一种化大为小,分而治之的软件开发方法。
分层的特点:
1.每一层都有自己的职责;
2.上层不用关心下次的实现细节,上层通过下层提供的对外接口来使用其功能;
3.上一层调用下一层的功能,下一层不能调用上一层的功能。
分层开发的好处:
1.各层专注于自己功能的实现,便于提高质量;
2.便于分工协作,提高开发效率;
3.便于代码复用;
4.便于程序扩展。分层原则:
1.封装性原则:每个层次向外公开接口,但是隐藏内部细节
2.顺序访问原则:下一层为上一层服务,但不使用上层的服务分层结构中,不同层之间通过实体类传输数据。
根据分层开发DAO模式创建步骤
1:建立数据库,建表;
2:创建实体类,和相应的数据库的表是对应的;
3:创建Dao的基类接口类;
4:创建Dao的通用实现类;
5:创建具体表的Dao类;
6:创建具体表的Dao实现类;
7 : 创建业务逻辑层的接口类;
8:创建业务逻辑层的接口实现类;
9 : 创建测试类。
第一步:建库建表:略
第二步:创建实体类
package com.jdbcLean; import java.io.Serializable; import java.sql.Blob; import java.sql.Date; public class User implements Serializable { private static final long serialVersionUID = 4131873907877763625L; private int id; private String userName; private String password; private Date date; private String address; private Blob picture; public User(){} public User(int id, String userName, String password, Date date, String address, Blob picture) { this.id = id; this.userName = userName; this.password = password; this.date = date; this.address = address; this.picture = picture; } public User(int id, String userName, String password, Date date, String address) { this.id = id; this.userName = userName; this.password = password; this.date = date; this.address = address; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Blob getPicture() { return picture; } public void setPicture(Blob picture) { this.picture = picture; } @Override public String toString() { return "User{" + "userId=" + id + ", userName='" + userName + '\'' + ", password='" + password + '\'' + ", date=" + date + ", address='" + address + '\'' + '}'; } }
第三步:创建Dao的基类接口
package com.jdbcLean; import java.sql.Connection; import java.util.List; import java.sql.SQLException; /** * 访问数据库的Dao接口。 * 其中定义了访问数据库的方法:DELETE,UPDATE,QUERY,INSERT,BATCH */ public interface Dao<T> { /** * INSERT,UPDATE,DELETE * @param sql:SQL语句 * @param connection:数据库连接 * @param args:填充占位符的可变参数 */ int update(Connection connection, String sql, Object... args) throws SQLException ; /** * INSERT,UPDATE,DELETE * @param sql:SQL语句 * @param args:填充占位符的可变参数 */ int update(String sql, Object... args) throws SQLException; /** * INSERT,UPDATE,DELETE * @param sql:SQL语句 */ int update(String sql) throws SQLException ; /** * INSERT,UPDATE,DELETE * @param sql:SQL语句 * @param connection:数据库连接 */ int update(Connection connection, String sql) throws SQLException; /** * 返回一个 T 的对象 * @param sql:SQL语句 * @return */ T queryObject(/*Class<T> clazz, */String sql) throws SQLException ; /** * 返回一个 T 的对象 * @param sql:SQL语句 * @return */ T queryObject(/*Class<T> clazz, */Connection connection, String sql) throws SQLException ; /** * 返回一个 T 的对象 * @param sql:SQL语句 * @param args:填充占位符的可变参数 * @return */ T queryObject(/*Class<T> clazz, */String sql, Object... args) throws SQLException ; /** * 返回一个 T 的对象 * @param sql:SQL语句 * @param args:填充占位符的可变参数 * @return */ T queryObject(/*Class<T> clazz, */Connection connection, String sql, Object... args) throws SQLException ; /** * 返回 T 的一个集合 * @param sql:SQL语句 * @param args:填充占位符的可变参数 * @return */ List<T> queryObjects(/*Class<T> clazz, */Connection connection, String sql, Object... args) throws SQLException ; /** * 返回一个具体的值 * @param sql:SQL语句 * @param args:填充占位符的可变参数 * @return */ <E> E getValue(Connection connection, String sql, Object... args) throws SQLException; /** * 批量处理方法 * @param sql:SQL语句 * @param args:填充占位符的Object[]类型的可变参数 * @return */ void batch(Connection connection, String sql, Object[]... args) throws SQLException; }
第四步:创建Dao的通用实现类
package com.jdbcLean; import java.lang.reflect.ParameterizedType; import com.jdbcLean.Dao; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import javax.sql.DataSource; import java.sql.*; import java.util.List; /** * 能否解决高并发读写操作问题? * * 如何利用工厂模式使用Dao? * * ThreadLocal管理conn进行事务处理的案例:https://blog.csdn.net/weisubao/article/details/52575787 * QueryRunner(DataSource ds)构造方法的实际用处:https://www.oschina.net/question/273800_55356 * 利用反射搭建项目的dao层:http://www.mamicode.com/info-detail-1552193.html * JDBC中Dao层:https://blog.csdn.net/whycmpx/article/details/78901875 * 关于JDBC和DAO模式使用:https://www.cnblogs.com/qi-dian/p/6185545.html * @param <T> : 子类需传入的泛型类型. */ public class JdbcDaoImpl<T> implements Dao<T>{ //QueryRunner是线程安全的 private QueryRunner queryRunner = null; private Class<T> type; protected DataSource dataSource; public JdbcDaoImpl(){ this.dataSource = null; this.init(); } public JdbcDaoImpl(DataSource dataSource){ this.dataSource = dataSource; this.init(); } @SuppressWarnings("unchecked") protected void init(){ this.queryRunner = new QueryRunner(); // 通过反射, 获得 Class 定义中声明的父类的泛型参数类型 // 如: CustomerDao extends JdbcDaoImpl<User> type = (Class <T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } protected Connection prepareConnection() throws SQLException { if (this.getDataSource() == null) { throw new SQLException("dataSource is null."); } else { return this.getDataSource().getConnection(); } } public DataSource getDataSource() { return this.dataSource; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public int update(String sql) throws SQLException { Connection connection = this.prepareConnection(); return this.update(connection, sql, (Object[])null); } @Override public int update(Connection connection, String sql) throws SQLException { return this.update(connection, sql, (Object[])null); } @Override public int update(String sql, Object... args) throws SQLException { Connection connection = this.prepareConnection(); return this.update(connection, sql, args); } /** * UPDATE,INSERT,DELETE * @param connection:数据库连接 * @param sql:SQL语句 * @param args:填充占位符的可变参数 * @return * @throws SQLException */ @Override public int update(Connection connection, String sql, Object... args) throws SQLException { if (connection == null) { throw new SQLException("Null connection"); } else if (sql == null) { this.closeConnection(connection); throw new SQLException("Null SQL statement"); } int rows = 0; try{ //事物开始 rows = queryRunner.update(connection,sql,args); //事物提交 }catch(Exception e){ //发生异常,事物回滚 e.printStackTrace(); } finally { this.closeConnection(connection); } return rows; } @Override public T queryObject(/*Class<T> clazz, */String sql) throws SQLException { Connection connection = this.prepareConnection(); return this.queryObject(/*clazz,*/connection,sql,(Object[]) null); } @Override public T queryObject(/*Class<T> clazz, */Connection connection, String sql) throws SQLException { return this.queryObject(/*clazz,*/connection,sql,(Object[]) null); } @Override public T queryObject(/*Class<T> clazz, */String sql, Object... args) throws SQLException { Connection connection = this.prepareConnection(); return this.queryObject(/*clazz,*/connection,sql,args); } @Override public T queryObject(/*Class<T> clazz, */Connection connection, String sql, Object... args) throws SQLException { if (connection == null) { throw new SQLException("Null connection"); } else if (sql == null) { this.closeConnection(connection); throw new SQLException("Null SQL statement"); } T entity = null; try { //可以通过反射, 获得 Class 定义中声明的父类的泛型参数类型, 因此就不再需要传入Class类型了. ResultSetHandler<T> rsh = new BeanHandler<T>(/*clazz*/type); boolean flag = args == null ? true : false; if (flag){ entity = queryRunner.query(connection,sql,rsh); } else { entity = queryRunner.query(connection,sql,rsh,args); } }catch(Exception e){ e.printStackTrace(); } finally { this.closeConnection(connection); } return entity; } @Override public List<T> queryObjects(/*Class<T> clazz, */Connection connection, String sql, Object... args) throws SQLException { if (connection == null) { throw new SQLException("Null connection"); } else if (sql == null) { this.closeConnection(connection); throw new SQLException("Null SQL statement"); } List<T> resultList = null;//new ArrayList<>(); try { ResultSetHandler<List<T>> rsh = new BeanListHandler<T>(/*clazz*/type); boolean flag = args == null ? true : false; if (flag){ resultList = queryRunner.query(connection,sql,rsh); } else { resultList = queryRunner.query(connection,sql,rsh,args); } }catch(Exception e){ e.printStackTrace(); } finally { this.closeConnection(connection); } return resultList; } @Override public <E> E getValue(Connection connection, String sql, Object... args) throws SQLException { if (connection == null) { throw new SQLException("Null connection"); } else if (sql == null) { this.closeConnection(connection); throw new SQLException("Null SQL statement"); } E value = null; try { //第一行的第一列 ResultSetHandler<E> rsh = new ScalarHandler<E>(); value = queryRunner.query(connection,sql,rsh,args); }catch(Exception e){ e.printStackTrace(); } finally { this.closeConnection(connection); } return value; } @Override public void batch(Connection connection, String sql, Object[]... args) throws SQLException { if (connection == null) { throw new SQLException("Null connection"); } else if (sql == null) { this.closeConnection(connection); throw new SQLException("Null SQL statement"); } queryRunner.batch(connection, sql, args); } public void closeConnection(Connection connection) throws SQLException { if (null != connection){ connection.close(); } } }
通过返回获取获得定义 Class 时声明的父类的泛型参数的类型:
/** * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型 * 如: public EmployeeDao extends BaseDao<Employee, String> * @param clazz * @param index * @return */ @SuppressWarnings("unchecked") public static Class getSuperClassGenricType(Class clazz, int index){ Type genType = clazz.getGenericSuperclass(); if(!(genType instanceof ParameterizedType)){ return Object.class; } Type [] params = ((ParameterizedType)genType).getActualTypeArguments(); if(index >= params.length || index < 0){ return Object.class; } if(!(params[index] instanceof Class)){ return Object.class; } return (Class) params[index]; }
第五步:创建具体表的Dao类和实现类(省去了接口类)
package com.jdbcLean; public class CustomerDao extends JdbcDaoImpl<User> { public CustomerDao(){ super(); } public User getUser() throws Exception { String selectSql = "SELECT * FROM userinfos WHERE userName = ?"; return super.queryObject(JdbcUtils.getConnection(),selectSql,"aerfa"); } public int update() throws Exception { String updateSql = "UPDATE userinfos SET userName='Tom',password='admin123' WHERE id=?"; return super.update(JdbcUtils.getConnection(),updateSql,19); } public int insert() throws Exception { String insertSql = "INSERT INTO userinfos(userName,password,address) VALUES(?,?,?)"; return super.update(JdbcUtils.getConnection(),insertSql,"hq","heqiang123","chengdu"); } public int delete() throws Exception { String deleteSql = "DELETE FROM userinfos WHERE id = ?"; return super.update(JdbcUtils.getConnection(),deleteSql,21); } public Object getValue() throws Exception { String getSql = "SELECT password FROM userinfos WHERE userName = ?"; return super.getValue(JdbcUtils.getConnection(),getSql,"Tom"); } }
第六步:创建业务逻辑层的接口类和实现类(省去了接口类)
package com.jdbcLean; public class UserServer { }
第七步:创建测试类
package com.jdbcLean; public class DbutilsImplDaoTest { public static void main(String[] args) throws Exception { CustomerDao dao = new CustomerDao(); System.out.println(dao.getUser()); System.out.println(dao.update()); System.out.println(dao.insert()); System.out.println(dao.delete()); System.out.println(dao.getValue()); } }
数据库连接 与 数据库事物
//后面更新... ...
参考内容: