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 ...
随机推荐
- AI体验类产品竞品分析
1.业界状态 人工智能(Artificial Intelligence),简称AI.上个世纪50年代就有一批年轻的科学家提出了这一概念,经历过50多年的长足发展,信息化建设的脚步不断加快,机器人战胜人 ...
- Java程序员必读的9本书
本文列出的9本书在Java程序员界都是被认为很棒的书.当一个程序员开始初学Java时,他的第一个问题应该是如何选择一本书来作为指导学习Java.这个问题也就表明,相对于其他的教程和博客,Java书籍还 ...
- Material Design 组件之NavigationView
今天来看一下 NavigationView 的使用,NavigationView 是一个标准的导航菜单,其菜单内容由菜单资源文件来填充,NavigationView 一般和 DrawerLayout ...
- js之for与forEach循环的区别
回武汉打卡第四天,武汉加油,逆战必胜!今天咱们探讨一下for循环和forEach()循环的区别. 首先,for循环在最开始执行循环的时候,会建立一个循环变量i,之后每次循环都是操作这个变量,也就是说它 ...
- 十进制转化为非十进制C++代码
还是先为大家介绍一下原理吧. 假设余数为 r ,十进制数为 n :(拆分为整数 zs ,余数 ys) 对 zs:需要将 zs 除 r 取余数,直到商为 0 停止,将余数倒序排列即可. 对 ys:需要将 ...
- Codeforces Round #628 (Div. 2)
1325A - EhAb AnD gCd 题意:随意找两个数是他们的最大公约数 GCD 与最小公倍数 LCM 之和为所给定的值. 思路:找一下规律 ,假设所给的 数位n, 那么我们将n分成 1 ,n- ...
- 7行代码搞定WEB服务
作为一个 Java 程序猿,写代码久了,各种技术也就都尝试了一个遍. 先从 SSH1(Spring.Struts1.Hibernate)摸爬滚打转变到 SSH2(Spring.Struts2.Hibe ...
- C#通用类库整理--字符串处理类
在程序开发中通常需要将字符串转为自己想要的结果,以下三个类库主要实现: 1.GetStrArray(string str, char speater, bool toLower) 把字符串按照分隔符 ...
- PTA数据结构与算法题目集(中文) 7-9
PTA数据结构与算法题目集(中文) 7-9 7-9 旅游规划 (25 分) 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游 ...
- Java第二十七天,线程池
1.什么情况下需要线程池? 频絮创建线程就会大大降低系统的效率,那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?在java中可以通过线程池来达到这样的效 ...