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 ...
随机推荐
- LVS 负载均衡 三种工作模式 十种调度算法
原文链接:https://blog.csdn.net/weixin_40470303/article/details/80541639 一.LVS简介 LVS(Linux Virtual Server ...
- 火焰图--记一次cpu降温过程
引子 正值周末,娃儿6:30又如闹铃般准时来叫醒了我们.年前离开美菜,又回到了杭州.原本是想有更多时间陪伴娃儿,然而新的工作节奏与工作地点,让我们每天都是早上见面:这不,为了周末可以多玩一会儿,早早就 ...
- 403 Invalid CORS request 跨域问题
5.跨域问题 跨域:浏览器对于javascript的同源策略的限制 . 以下情况都属于跨域: 跨域原因说明 示例 域名不同 www.jd.com 与 www.taobao.com 域名相同,端口不同 ...
- CVE-2020-2551复现过程
项目地址 cnsimo/CVE-2020-2551 CVE-2020-2551 weblogic iiop 反序列化漏洞 该项目的搭建脚本在10.3.6版本经过测试,12版本未测试. 环境 kali+ ...
- Linux中的基础
前言: 这里介绍Linux基础管理.主要包括.Linux中的帮助命令(man.help).系统基础(开机.关机.重启) 一.Linux中的帮助命令. 1.内部命令: #help 命令名 例如:help ...
- CSS躬行记(3)——CSS属性拾遗
一.粘滞定位 粘滞定位(sticky)与相对定位类似,既不会脱离正常流,也不会改变元素盒类型,并且会保留原先所占的空间.它会相对于包含块偏移,它的包含块分为两种,第一种和绝对定位一样:第二种是最近的滚 ...
- 泛型代码中的 default 关键字
在泛型类和泛型方法中会出现的一个问题是,如何把缺省值赋给参数化类型,此时无法预先知道以下两点: l T将是值类型还是引用类型 l 如果T是值类型,那么T将是数值还是结构 对 ...
- 携程首页--使用flex布局实现
携程首页 flex解决了float和postion的遗留问题,对移动端比较友好. 需要水平排列的元素就为其父元素设置display:flex,并为子元素添加flex的值(比例) 布局时可以先从大的页面 ...
- 批处理 bat 查询局域网内在线电脑IP
查看自己局域网的IP和物理网卡地址可以在 WIN+R –> 打开cmd 键入 arp -a 可以看到局域网中所有的在线IP COLOR 0A CLS @ECHO Off Title 查询局域网内 ...
- String 对象-->判断是否相等
1.定义和用法 == 值相等 === 绝对相等(值和类型都相等) 举例: var str = '8' var str1 = 8 console.log(str == str1) console.log ...