JDBC 进阶:使用封装通用DML DQL 和结构分层以及at com.mysql.jdbc.PreparedStatement.setTimestamp空指针异常解决
准备:
- 数据表
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(10) DEFAULT NULL,
`pwd` varchar(10) DEFAULT NULL,
`regTime` date DEFAULT NULL,
`lastLoginTime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20227 DEFAULT CHARSET=utf8;

- jar包:

注意! 我这里使用的驱动包时5.1.48
如果使用了5.1.47会有个setTimestamp的空指针异常,网上有大神建议回退到5.1.46;
不过新版本出来了,我这边就使用新版本了。
这个bug MySQL官网有说明
[6 Jul 2019 0:44] Daniel So
Posted by developer:
Added the following entry to the Connector/J 5.1.48 changelog:
"PreparedStatement.setTimestamp threw a NullPointerException if getParameterMetaData() was called before the statement was executed. This fix adds the missing null checks to getParameterMetaData() to avoid the exception."
搭建分层结构

编写配置文件
driver = com.mysql.jdbc.Driver
jdbcUrl = jdbc:mysql://localhost:3306/testjdbc?useSSL=false
username = root
userpassword = 123456
编写工具类
package com.xzlf.commons;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
public class JdbcUtil {
private static String driver;
private static String jdbcUrl;
private static String username;
private static String userpassword;
static {
// 读取properties 文件
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
driver = bundle.getString("driver");
jdbcUrl = bundle.getString("jdbcUrl");
username = bundle.getString("username");
userpassword = bundle.getString("userpassword");
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取connection 对象
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(jdbcUrl, username, userpassword);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 释放资源
* @param rs
* @param stat
* @param conn
*/
public static void closeResource(ResultSet rs, Statement stat, Connection conn) {
try {
if(rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stat != null) {
stat.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
编写pojo
package com.xzlf.pojo;
import java.sql.Date;
import java.sql.Timestamp;
public class User {
private Integer id;
private String username;
private String pwd;
private Date regTime;
private Timestamp lastLoginTime;
public User() {
// TODO Auto-generated constructor stub
}
public User(Integer id, String username, String pwd, Date regTime, Timestamp lastLoginTime) {
super();
this.id = id;
this.username = username;
this.pwd = pwd;
this.regTime = regTime;
this.lastLoginTime = lastLoginTime;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Date getRegTime() {
return regTime;
}
public void setRegTime(Date regTime) {
this.regTime = regTime;
}
public Timestamp getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Timestamp lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", pwd=" + pwd + ", regTime=" + regTime
+ ", lastLoginTime=" + lastLoginTime + "]";
}
}
编写通用的BaseDAO接口
package com.xzlf.dao;
import java.util.List;
public interface BaseDao {
int executeUpdate(String sql, Object[] param);
public <T> List<T> find(String sql, Object[] param, Class<T> clazz);
}
编写到具体的DAO接口
package com.xzlf.dao;
import java.util.List;
import com.xzlf.pojo.User;
public interface UserDao extends BaseDao {
int insertUser(User user);
int updteUser(User user);
int deleteUser(int id);
List<User> selectUserByLikeName(String username);
}
编写通用的BaseDAO接口实现
package com.xzlf.dao.impl;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import com.xzlf.commons.JdbcUtil;
import com.xzlf.dao.BaseDao;
public class BaseDaoImpl implements BaseDao{
/**
* 封装通用的DML操作
*/
@Override
public int executeUpdate(String sql, Object[] param) {
Connection conn = null;
PreparedStatement ps = null;
int rows = 0;
try {
conn = JdbcUtil.getConnection();
ps = conn.prepareStatement(sql);
// 获取参数信息
ParameterMetaData parameterMetaData = ps.getParameterMetaData();
// 获取参数个数
int count = parameterMetaData.getParameterCount();
// 绑定参数
for (int i = 0; i < count; i++) {
ps.setObject(i + 1, param[i]);
}
rows = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtil.closeResource(null, ps, conn);
}
return rows;
}
/**
* 封装通用的查询操作
* 注意:通用的查询方法中要求模型对象的属性名必须要和数据库表中的列名相同。
*/
@Override
public <T> List<T> find(String sql, Object[] param, Class<T> clazz) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<T> list = new ArrayList<T>();
try {
conn = JdbcUtil.getConnection();
ps = conn.prepareStatement(sql);
ParameterMetaData parameterMetaData = ps.getParameterMetaData();
int count = parameterMetaData.getParameterCount();
for (int i = 0; i < count; i++) {
ps.setObject(i + 1, param[i]);
}
rs = ps.executeQuery();
// 获取结果集信息
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while(rs.next()) {
// 通过反射完成ORM 处理
T bean = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
// 获取列名(约定和对象属性名)
String columnName = metaData.getColumnName(i + 1);
// 获取列值
Object value = rs.getObject(columnName);
// 通过BeanUtil 工具类,把值写到对象中
BeanUtils.setProperty(bean, columnName, value);
}
list.add(bean);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
JdbcUtil.closeResource(rs, ps, conn);
}
return list;
}
}
编写到具体的DAO接口实现
package com.xzlf.dao.impl;
import java.util.List;
import com.xzlf.dao.UserDao;
import com.xzlf.pojo.User;
public class UserDaoImpl extends BaseDaoImpl implements UserDao{
// 添加用户信息
@Override
public int insertUser(User user) {
String sql = "insert into t_user values(default, ?, ?, ?, ?)";
Object[] param = {user.getUsername(), user.getPwd(), user.getRegTime(), user.getLastLoginTime()};
return this.executeUpdate(sql, param);
}
// 更新用户信息
@Override
public int updteUser(User user) {
String sql = "update t_user set username=?, pwd=?, regTime=?, LastLoginTime=? where id=?";
Object[] param = {user.getUsername(), user.getPwd(),
user.getRegTime(), user.getLastLoginTime(), user.getId()};
return this.executeUpdate(sql, param);
}
// 删除用户信息
@Override
public int deleteUser(int id) {
String sql = "delete from t_user where id=?";
Object[] param = {id};
return this.executeUpdate(sql, param);
}
// 查询用户信息
@Override
public List<User> selectUserByLikeName(String username) {
String sql = "select * from t_user where username like ?";
Object[] param = {"%" + username + "%"};
return this.find(sql, param, User.class);
}
}
编写业务层接口
package com.xzlf.service;
import java.util.List;
import com.xzlf.pojo.User;
public interface UserService {
int addUser(User user);
int modifyUser(User user);
int dropUser(int id);
List<User> findUser(String username);
}
编写业务层实现
package com.xzlf.service.impl;
import java.util.List;
import com.xzlf.dao.UserDao;
import com.xzlf.dao.impl.UserDaoImpl;
import com.xzlf.pojo.User;
import com.xzlf.service.UserService;
public class UserServiceImpl implements UserService{
private UserDao userDao = new UserDaoImpl();
@Override
public int addUser(User user) {
return this.userDao.insertUser(user);
}
@Override
public int modifyUser(User user) {
return this.userDao.updteUser(user);
}
@Override
public int dropUser(int id) {
return this.userDao.deleteUser(id);
}
@Override
public List<User> findUser(String username) {
return this.userDao.selectUserByLikeName(username);
}
}
编写视图层
……
暂无
……
编写测试类
package com.xzlf.test;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;
import org.junit.Test;
import com.xzlf.pojo.User;
import com.xzlf.service.UserService;
import com.xzlf.service.impl.UserServiceImpl;
public class TestApp {
private UserService userService = new UserServiceImpl();
@Test
public void testAddUser() {
User user = new User();
user.setUsername("盖伦");
user.setPwd("123123");
user.setRegTime(new Date(System.currentTimeMillis() - 3600*24*1000));
user.setLastLoginTime(new Timestamp(System.currentTimeMillis()));
this.userService.addUser(user);
}
@Test
public void testModifyUser() {
User user = new User();
user.setId(20223);
user.setUsername("赵信");
user.setPwd("666666");
user.setRegTime(new Date(System.currentTimeMillis() - 3600*24*2000));
user.setLastLoginTime(new Timestamp(System.currentTimeMillis()));
this.userService.modifyUser(user);
}
@Test
public void testDropUser() {
this.userService.dropUser(20223);
}
@Test
public void testFindUser() {
List<User> users = this.userService.findUser("麻子");
for (User user : users) {
System.out.println(user);
}
}
}
查询方法打印了截个图:

JDBC 进阶:使用封装通用DML DQL 和结构分层以及at com.mysql.jdbc.PreparedStatement.setTimestamp空指针异常解决的更多相关文章
- JDBC的一些简单通用代码
JDBC的一些简单通用代码 功能包括 连接数据库 查询操作 执行sql语句 jdbc相关类的加载 关闭连接 获取数据库格式的当前时间 代码 package dao; import java.sql.C ...
- 数据库 MySQL Jdbc JDBC的六个固定步骤
*0 案例: a)在JavaScript中使用正则表达式,在JS中正则表达式的定界符是:// var regexp = /^[0-9]+$/; if(regexp.test(nu ...
- MySQL -- JDBC
一 . JDBC的开发步骤 1.准备四大参数 2.注册驱动 3.获得连接 4.获得语句执行者 5.执行sql语句 6.处理结果 7.释放资源 1.准备四大参数 /* * jdbc四大配置参数 * &g ...
- com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 解决办法
09:00:30.307 [http-8080-6] ERROR org.hibernate.transaction.JDBCTransaction -JDBC begin failed com.my ...
- 【转】关于Class.forName(“com.mysql.jdbc.Driver”)
原文:http://www.cnblogs.com/gaojing/archive/2012/03/23/2413638.html 传统的使用jdbc来访问数据库的流程为: Class.forName ...
- com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 数据库报错
-- 查询mysql 数据库链接空闲时间持有最大空闲时间,单位为秒 SHOW VARIABLES WHERE VAriable_name = 'interactive_timeout'; -- 会出现 ...
- Class.forName("com.mysql.jdbc.Driver");的作用
对于大的项目当然我们都已经有了原有基本框架,但是对于一些新的技术探讨的时候,我们还是直接调用Class.forName("com.mysql.jdbc.Driver")连接数据库进 ...
- 关于Class.forName(“com.mysql.jdbc.Driver”)--转
传统的使用jdbc来访问数据库的流程为:Class.forName(“com.mysql.jdbc.Driver”);String url = “jdbc:mysql://localhost:3306 ...
- MYSQL超时连接问题(com.mysql.jdbc.MysqlIO.readFully)
应用服务器连接mysql,有时候会出现以下异常: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.jav ...
随机推荐
- coding++:RateLimiter 限流算法之漏桶算法、令牌桶算法--简介
RateLimiter是Guava的concurrent包下的一个用于限制访问频率的类 <dependency> <groupId>com.google.guava</g ...
- [vijos1782]借教室<线段树>
题目链接:https://vijos.org/p/1782 题意:一个区间1,n.m次操作,每次操作让l,r区间值减去d,当有任何一个值小于0就输出当前是第几个操作 这道题其实是没有什么难度的,是 ...
- WebView中Java与JavaScript的交互
原文首发于微信公众号:jzman-blog,欢迎关注交流! Android 开发过程中 WebView 的使用比较广泛,常用来加载网页,比如使用 WebView 加载新闻页面.使用 WebView 打 ...
- PTA数据结构与算法题目集(中文) 7-43字符串关键字的散列映射 (25 分)
PTA数据结构与算法题目集(中文) 7-43字符串关键字的散列映射 (25 分) 7-43 字符串关键字的散列映射 (25 分) 给定一系列由大写英文字母组成的字符串关键字和素数P,用移位法定义 ...
- qq群排名靠前最新方法
QQ群排名这几年是越来越火,因为很多灰产业都选择做QQ群排名,毕竟没有那么严,那么要做QQ群排名虽然不难,但是还是需要一点技术和软件的. https://url.cn/5JbR4C8 QQ群排名分为如 ...
- 一天学一个Linux命令:第一天 ls
文章更新于:2020-03-02 注:本文参照 man ls 手册,并给出使用样例. 文章目录 一.命令之`ls` 1.名字及介绍 2.语法格式 3.输出内容示例 4.参数 二.命令实践 1.`ls ...
- 家庭版记账本app开发进度。开发到现在整个app只剩下关于图表的设计了,具体功能如下
首先说一下自己的功能: 实现了用户的登录和注册.添加收入记账和添加支出记账.粗略显示每条账单基本情况.通过点击每条账单来显示具体的情况, 之后就是退出当前用户的操作. 具体的页面情况如下: 这就是整个 ...
- 2017蓝桥杯购物单(C++B组)
原题: 标题: 购物单 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞.这不,XX大促销又来了!老板夫人开出了长长的购物单,都是 ...
- Linux忘记密码解决方案
Linux 忘记密码解决方法 很多朋友经常会忘记Linux系统的root密码,linux系统忘记root密码的情况该怎么办呢?重新安装系统吗?当然不用!进入单用户模式更改一下root密码即可. 步骤如 ...
- std::string::insert函数
string& insert (size_t pos, const string& str); string& insert (size_t pos, const string ...