这个项目用到jdbc技术,研究了一下,为了学习一下,对于执行sql语句,自己进行封装工具类来进行处理,这样便于进一步理解。
首先我们来看一下搭建的基本项目结构
我们接下来看一下相关的配置信息:
首先看一下web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--解决post乱码问题--> <filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!--设置UTF-8编码--> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置servlet的前端控制器--> <servlet> <servlet-name>mySpringMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--指定servlet的配置文件,默认情况下servlet的配置文件在/WEB-INF/${servlet-name}-servlet.xml文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <!--这个就是指定项目初识启动时就要初始化--> <load-on-startup>1</load-on-startup> </servlet> <!--配置拦截请求--> <servlet-mapping> <!--指定控制器--> <servlet-name>mySpringMvc</servlet-name> <!--拦截所有请求,不包括jsp,但是包括所有js,css,png等--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
接下来看一下我们的spring 的配置文件applicationContext.xml
<!--配置注解扫描--> <context:component-scan base-package="com.yang" /> <!--因为配置了静态文件,spring不会自动为我们加载HandlerMapping与HandlerAdapter,因此需要进行初始化--> <mvc:annotation-driven /> <!--配置静态文件--> <mvc:resources location="WEB-INF/static/images" mapping="/images/**" /> <mvc:resources location="WEB-INF/static/js" mapping="/js/**" /> <mvc:resources location="WEB-INF/static/css" mapping="/css/**" /> <!--上传文件配置--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8" /> <property name="maxUploadSize" value="5120" /> </bean> <!--配置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/page/" /> <property name="suffix" value=".jsp" /> </bean>
为了进行封装JDBC的增删改查,我们首先先封装一下JDBC查询出的结果集
首先定义一个接口,定义一下我们的这个结果集如何进行处理IResultSetHandler
package com.yang.handler; import java.sql.ResultSet; /** * 定义结果集的处理函数 * * @param <T> 范型,指定处理类型 */ public interface IResultSetHandler<T> { T handle(ResultSet rs) throws Exception; }
接下来对于单一以及列表的Bean进行处理
BeanHandler
package com.yang.handler; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.sql.ResultSet; /** * 设置查询单一类型的结果集处置方法 * * @param <T> 范型 */ public class BeanHandler<T> implements IResultSetHandler<T> { private Class<T> classType; // 构造函数,设置当前类型的类 public BeanHandler(Class<T> classType) { this.classType = classType; } // 处理函数 @Override public T handle(ResultSet rs) throws Exception { // 结果集有结果开始处理 if (rs.next()) { // 1。实例化一个当前处理类型的对象 T obj = this.classType.getDeclaredConstructor().newInstance(); // 2。获取这个类型信息,属性, Object.class就是删除那个默认的class的属性 BeanInfo beanInfo = Introspector.getBeanInfo(this.classType, Object.class); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { // 从结果集中,获取对应的属性值 Object object = rs.getObject(propertyDescriptor.getName()); // 利用反射,调用set方法,为对象赋值 propertyDescriptor.getWriteMethod().invoke(obj, object); } return obj; } return null; } }
BeanListHandler
package com.yang.handler; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class BeanListHandler<T> implements IResultSetHandler<List<T>> { private Class<T> classType; public BeanListHandler(Class<T> classType) { this.classType = classType; } @Override public List<T> handle(ResultSet rs) throws Exception { // 1。初始化一个列表,存储我们的对象 List<T> list = new ArrayList<>(); while (rs.next()) { // 2。实例化一个当前处理类型的对象 T obj = this.classType.getDeclaredConstructor().newInstance(); // 3。获取这个类型信息,属性, Object.class就是删除那个默认的class的属性 BeanInfo beanInfo = Introspector.getBeanInfo(this.classType, Object.class); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { // 4。从结果集中,获取对应的属性值 Object object = rs.getObject(propertyDescriptor.getName()); // 5。利用反射,调用set方法,为对象赋值 propertyDescriptor.getWriteMethod().invoke(obj, object); } // 6。向列表添加对象 list.add(obj); } return list; } }
我们使用的是德鲁伊连接池,我们直接将其的获取数据库连接以及关闭连接记性封装,避免进行重复操作
JdbcUtil
package com.yang.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JdbcUtil { // 声明一个数据库资源,方便后续进行操作 public static DataSource ds = null; static { // 1. 初始化读取资源文件 Properties properties = new Properties(); try { // 2. 读取mysql的配置信息到内存中 FileInputStream fileInputStream = new FileInputStream("resources/mysql.properties"); // 3. 转化配置信息 properties.load(fileInputStream); // 4。 生成德鲁伊数据库连接吃池 ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } // 从数据库连接中获取连接对象 public static Connection getConn(){ try{ return ds.getConnection(); }catch (Exception e){ e.printStackTrace(); } return null; } /** * 关闭数据库连接对象,释放资源,数据库连接池关闭对象就会把连接放回池中,而不是关闭 * @param conn 连接对象 * @param st 连接语句 * @param rs 查询结果集 */ public static void close(Connection conn, Statement st, ResultSet rs){ // 关闭结果集 if(rs!=null){ try{ rs.close(); }catch (SQLException e){ e.printStackTrace(); } } // 关闭查询 if(st!=null){ try{ st.close(); }catch (SQLException e){ e.printStackTrace(); } } // 关闭连接对象 if(conn!=null){ try{ conn.close(); }catch (SQLException e){ e.printStackTrace(); } } } }
为了对数据的增删改查进行封装,为进一步学习,我们自己进行封装
CRUDTemplete
package com.yang.util; import com.yang.handler.IResultSetHandler; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * 为了方便学习,自己封装一个JDBC的增删改查的工具类,等同于dbUtil */ public class CRUDTemplate { private static Connection conn = null; private static PreparedStatement ps = null; private static ResultSet rs = null; static { conn = JdbcUtil.getConn(); } // 这个执行增删改操作,params必须与sql语句中的位置一一对应 public static int executeUpdate(String sql, Object... params) { try { assert conn != null; ps = conn.prepareStatement(sql); // 使用prepareStatement的方法为指定位置添加传入参数 for (int i = 0; i < params.length; i++) { ps.setObject(i + 1, params[i]); } return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { // 最终关闭资源 JdbcUtil.close(conn, ps, rs); } // 如果有报错,则返回0 return 0; } // 执行查询操作 public static <T> T executeQuery(String sql, IResultSetHandler<T> rh, Object... params) { try { // 预执行sql语句 ps = conn.prepareStatement(sql); // 将参数传入预执行语句 for (int i = 0; i < params.length; i++) { ps.setObject(i + 1, params[i]); } // 执行sql语句并获取结果集 rs = ps.executeQuery(); // 调用传入的结果集处理方法,进行处理 return rh.handle(rs); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, ps, rs); } return null; } }
我们首先来看一下user的dao层对象应当如何编写
IUserDao
package com.yang.dao; import com.yang.domain.User; public interface IUserDao { // 保存用户 boolean save(User user); // 删除用户,接受值int boolean delete(Integer id); // 更新用户 boolean update(Integer id, User user); // 获取用户 User get(Integer id); User get(String username); }
接下来看一下UserDao的实现类
UserDaoImpl
package com.yang.dao.impl; import com.yang.dao.IUserDao; import com.yang.domain.User; import com.yang.handler.BeanHandler; import com.yang.handler.IResultSetHandler; import com.yang.util.CRUDTemplate; import java.sql.ResultSet; public class UserDaoImpl implements IUserDao { // 新建用户 @Override public boolean save(User user) { // 创建sql语句 String sql = "insert into user(name, password, avatar_url, sex) values(?,?,?,?)"; // 使用工具类进行查询 int result = CRUDTemplate.executeUpdate(sql, user.getUsername(), user.getPassword(), user.getAvatarUrl(), user.getSex()); return result == 1; } // 根据id删除用户 @Override public boolean delete(Integer id) { String sql = "delete from user where id = ?"; int result = CRUDTemplate.executeUpdate(sql, id); return result == 1; } // 根据用户id以及上传的用户信息,进行修改用户信息 @Override public boolean update(Integer id, User user) { String sql = "update user set name = ?, password = ?, avatar_url = ?, sex = ? where id = ?"; int result = CRUDTemplate.executeUpdate(sql, user.getUsername(), user.getPassword(), user.getAvatarUrl(), user.getSex(), id); return result == 1; } // 根据id查询单个用户信息 @Override public User get(Integer id) { String sql = "select * from user where id = ?"; return CRUDTemplate.executeQuery(sql, new BeanHandler<User>(User.class), id); } // 根据用户名查询单个用户信息 @Override public User get(String username) { String sql = "select * from user where name = ?"; return CRUDTemplate.executeQuery(sql, new BeanHandler<User>(User.class), username); } }
这个就是简单的配置信息,如后续有需要,在添加其他配置。
github地址:GitHub
看一下引入的jar包