工具类封装、DAO模式和自定义连接池(java)
1.工具类封装
工具类封装主要将对数据库的操作全部提取出来放在DbUtils工具类中,从而实现代码的复用。实现代码分层效果,提高代码逻辑结构。在需要修改模块功能是,只需将部分代码修改即可。
案例实现:实现对emp表的查询、添加、删除、修改
1.1将加载驱动类,获取连接对象的参数写入配置文件,用类加载器加载配置文件,通过IO流读写文件获取参数值
配置文件:db.properties
[code]driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/myschool?useSSL=true&characterEncoding=utf8 username=root password=root
1.2封装DbUtils工具类 封装对emp表的增删改查
重点:对数据库中数据的查询(利用反射和内省机制)
查询基本步骤描述:查询表格中所有记录
(1)获取连接对象conn,执行命令对象pstat
(2)pstat执行SQL语句,将结果集返回给结果集对象rs
(3)通过结果集对象拿到表格列名集(表头名集)
(4)遍历结果集,通过列名集拿到每行每列的对应的值value
(5)用泛型类对象创建对象T t=class1.newInstance(),并用列名和泛型类对象获取属性描述符(与实体类中的每个属性相对应)
(6)用属性描述符得到每个属性的setXXX()方法,调用反射方法invoke(t,value);给每个属性赋值
(7)最后将赋值的t对象添加到list集合中,完成读取数据库中的数据,遍历输出。
[code]public class DbUtils { private static String driver; private static String url; private static String username; private static String password; static{ try { Properties prop = new Properties(); InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties"); prop.load(is); driver = prop.getProperty("driver"); url = prop.getProperty("url"); username = prop.getProperty("username"); password = prop.getProperty("password"); Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection(){ try { return DriverManager.getConnection(url,username,password); } catch (SQLException e) { System.out.println("连接失败!"); e.printStackTrace(); } return null; } public static void executeUpdate(String sql,Object...params){ Connection conn = DbUtils.getConnection(); if(conn!=null){ PreparedStatement pstat=null; try { pstat = conn.prepareStatement(sql); if(params!=null){ for (int i = 0; i < params.length; i++) { pstat.setObject(i+1,params[i]); } } pstat.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { release(conn,pstat,null); } } } public static <T> List<T> findAll(String sql, Object[] params, Class<T> class1){ List<T> list = new ArrayList<>(); Connection conn=null; PreparedStatement pstat=null; ResultSet rs=null; try { conn = DriverManager.getConnection(url,username,password); pstat = conn.prepareStatement(sql); rs = pstat.executeQuery(); while(rs.next()){ try { T t = class1.newInstance(); ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); // System.out.println(columnCount); for (int i = 0; i < columnCount; i++) { //得到每一列的列名 String columnLabel = metaData.getColumnLabel(i + 1); //得到这一行列名对应的值 Object object = rs.getObject(columnLabel); try { //得到每一列的属性描述符 PropertyDescriptor pd = new PropertyDescriptor(columnLabel,class1); if(pd!=null) { //根据属性描述符得到其set方法 Method writeMethod = pd.getWriteMethod(); //把每一列的值赋给实体类对应的属性 writeMethod.invoke(t, object); } } catch (Exception e) { // e.printStackTrace(); continue; } } list.add(t); } catch (Exception e) { e.printStackTrace(); } } } catch (SQLException e) { e.printStackTrace(); }finally { release(conn,pstat,rs); } return list; } public static <T> T findByEmpno(String sql,Class<T> class1,Object...params){ Connection conn=null; PreparedStatement pstat=null; ResultSet rs=null; T t = null; try { conn = DriverManager.getConnection(url,username,password); pstat = conn.prepareStatement(sql); pstat.setObject(1,params[0]); rs = pstat.executeQuery(); if(rs.next()){ try { t=class1.newInstance(); ResultSetMetaData metaData = rs.getMetaData(); for (int i = 0; i < metaData.getColumnCount(); i++) { String columnLabel = metaData.getColumnLabel(i + 1); Object value = rs.getObject(columnLabel); try { PropertyDescriptor pd = new Propert 7ff7 yDescriptor(columnLabel,class1); if(pd!=null){ Method writeMethod = pd.getWriteMethod(); writeMethod.invoke(t,value); } } catch (IntrospectionException e) { // e.printStackTrace(); continue; } } } catch (Exception e) { e.printStackTrace(); } } } catch (SQLException e) { e.printStackTrace(); } return t; } public static void release(Connection conn, Statement stat, ResultSet rs){ try { if(rs!=null){ rs.close(); } if(stat!=null){ stat.close(); } if(conn!=null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
以上封装好的工具类,配合DAO设计模式使用。
2.DAO设置模式
DAO(Database Access Object 数据库访问对象)
为了降低耦合性,提出了DAO封装数据库操作的设计模式。
它可以实现业务逻辑与数据库访问相分离。相对来说,数据库是比较稳定的,其中DAO组件依赖于数据库系统,提供数据库访问的接口,隔离了不同的数据库实现。
DAO模式的组成部分
1 DAO接口(主要包 添加 修改 查询 删除方法)
2 DAO实现类
3 实体类 (domain(领域)、beans、entity、pojo、model)
PO (VO)(Persistent Object, Value Object)
VO (View Object)
DTO (Data Transfer Object)
--作用:用在数据访问代码和业务逻辑代码之间通过实体类来传输数据
--实体类特征:
◦属性一般使用private修饰
◦提供public修饰的getter/setter方法
◦实体类提供无参构造方法,根据业务提供有参构造
◦实现java.io.Serializable接口,支持序列化机制
4 数据库连接和关闭工具类
设计的包名 :
domain 存放实体类
utils 存放工具类
dao 存放接口
dao.impl 存放实现类
DAO模式设计案例请参考https://blog.csdn.net/SjwFdb_1__1/article/details/100128177
3.自定义实现连接池
用户每次请求都需要向数据库获得连接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。
Java为连接池实现提供了一个规范(接口),规范的写法,我们需要实现DataSource接口!
案例如下:
注意:DataSource接口中有多个抽象方法,我们只需要实现getConnection方法,然后自己定义ralease()用于释放资源,把连接对象从新添加到连接池中。
[code]public class DbUtilsPool implements DataSource { private static String driver; private static String url; private static String username; private static String password; private static List<Connection> connections = Collections.synchronizedList(new LinkedList<>()); static{ try { Properties prop = new Properties(); InputStream is = DbUtils.class.getClassLoader().getResourceAsStream("db.properties"); prop.load(is); is.close(); driver = prop.getProperty("driver"); url = prop.getProperty("url"); username = prop.getProperty("username"); password = prop.getProperty("password"); Class.forName(driver); for (int i = 0; i < 5; i++) { Connection conn = DriverManager.getConnection(url, username, password); connections.add(conn); } } catch (Exception e) { e.printStackTrace(); } } //从连接池中取连接对象,存在返回连接对象,不存返回null @Override public Connection getConnection() throws SQLException { return connections.remove(0); } //将连接对象放回连接池中 public static void release(Connection conn){ connections.add(conn); } @Override public Connection getConnection(String s, String s1) throws SQLException { return null; } @Override public PrintWriter getLogWriter() throws SQLException { return null; } @Override public void setLogWriter(PrintWriter printWriter) throws SQLException { } @Override public void setLoginTimeout(int i) throws SQLException { } @Override public int getLoginTimeout() throws SQLException { return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } @Override public <T> T unwrap(Class<T> aClass) throws SQLException { return null; } @Override public boolean isWrapperFor(Class<?> aClass) throws SQLException { return false; } }
测试代码:
[code]public class DbUtilsPoolTest { @Test public void testGetConn(){ for (int i = 0; i < 8; i++) { DbUtilsPool myPool = new DbUtilsPool(); Connection conn = null; try { conn = myPool.getConnection(); System.out.println("连接"+conn.hashCode()+"成功!"); myPool.release(conn); } catch (Exception e) { System.out.println("连接超时,请重新连接......"); } } } }
测试结果:
会产生重复连接对象,因为在连接池共产生5个连接对象,当我们需要的连接对象大于5个,就会产生重复连接对象。
- MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
- MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
- DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
- JAVA入门,DAO设计模式
- Java EE WEB工程师培训-JDBC+Servlet+JSP整合开发之09.JDBC DAO设计模式
- day08_java面向对象(数组的工具类+单例设计模式+继承)
- DAO,接口,工厂模式,java类的动态加载,ioc
- JavaBean中DAO设计模式介绍(转)
- 07_数据库创建,添加c3p0操作所需的jar包,编写c3p0-config.xml文件,编写User.java,编写jdbcUtils.java实现操作数据库的模板工具类,UserDao编写,Dao
- Java面向接口编程(DAO模式)
- 在JAVA中封装JSONUtils工具类及使用(一)
- ★数组工具类的封装(static的应用) JAVA
- 在JAVA中封装JSONUtils工具类及使用
- java日期时间处理工具类封装
- 封装自定义数组类(java版线性表)
- Java Dao模式
- 在JAVA中封装JSONUtils工具类及使用
- Java基于自定义注释和反射机制实现初级通用DAO
- JavaDAO模式
- JAVA装饰模式,封装父类,提供转换接口(二)