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 ...
随机推荐
- poj——1182食物链 并查集(提升版)
因为是中文题,题意就不说了,直接说思路: 我们不知道给的说法中的动物属于A B C哪一类,所以我们可以用不同区间的数字表示这几类动物,这并不影响结果,我们可以用并查集把属于一类的动物放在一块,举个例子 ...
- HDU - 1160 最长上升子序列以及记录路径
题意:第一列,给出老鼠的重量,第二列,给出老鼠的速度,要证明老鼠的重量越大,速度越小,给出最多老鼠的数量,并说明第几只. 思路:先将老鼠按照重量从大到小排序,然后速度是从小到大,求最长上升子序列,学习 ...
- arcgis发布服务后显示证书不安全,将https改为http
arcgis server发布服务后显示证书不安全,无法浏览. 要通过https://localhost:port/arcgis/admin作如下修改 update之后地图服务会重启,耐心等待一会儿就 ...
- Java 垃圾回收机制方法,判断对象存活算法
垃圾回收机制: 不定时去堆内存中清理不可达对象.不可达的对象并不会马上就会直接回收, 垃圾收集器在一个Java程序中的执行是自动的,不能强制执行,即使程序员能明确地判断出有一块内存已经无用了,是应该回 ...
- .Net Web Api返回Json数据中原对象变量名大小写问题
这两天在工作中使用SignalR的WebSocket做数据实时传递的功能开发,在后端主动向前端广播数据以Json传递时,前端获取的Json中对应类的变量名首字母默认传递的是大写.而前端一直获取到的后台 ...
- ArrayList源码浅析
这里只理解主要的常用方法: 1 public class ArrayList<E> extends AbstractList<E> 2 implements List<E ...
- B 【ZJOI2007】时态同步
时间限制 : - MS 空间限制 : 265536 KB 评测说明 : 1s 256m 问题描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数 ...
- 001_创建一个sidebar切换页面
Table Of Content 准备 基本思路 实现 我们期望实现这样的效果: ; font-family: tahoma, arial, 宋体; font-size: 14px; line-h ...
- Redis 过期时间相关命令
命令 示例和描述 PERSIST PERSIST key-name —— 移除键的过期时间 TTL TTL key-name —— 查看给定键距离过期还有多少秒 EXPIRE EXPIRE key-n ...