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++:win10家庭版升级专业版方案
win10家庭版升级专业版密钥: VK7JG-NPHTM-C97JM-9MPGT-3V66T 4N7JM-CV98F-WY9XX-9D8CF-369TT FMPND-XFTD4-67FJC-HDR8C ...
- 瀑布流vue-waterfall的高度设置
最近用vue做项目,用到了瀑布流vue-waterfall,其中遇到高度的设置问题,大概介绍下,希望可以帮到一些人 1.安装 npm install --save vue-waterfall 2.引入 ...
- 泛型--->Result返回结果封装
controller的返回结果一般有两种: 1.Rest API JSON 输出 2.页面 目的:编写优雅的代码 实现:通过泛型对返回结果进行封装 代码如下: 一.控制层 /** * ...
- 查看手机wifi密码
方法一 手机共享wifi,获得二维码,之后解码获得密码. 二维码解吗工具: https://jiema.wwei.cn/ 方法二 手机扫描wifi共享的二维码后,会有提示信息,其中会显示出密码.
- 第一讲:Git分区,配置与日志
前言 曾经听到过这样一句话:不会git就不要敲代码了.细细品味确实有其中的道理,可能是当事人代码被强行覆盖后的叹息吧! 因此,为了避免这种情况,接下来我们就一起来好好学习git的相关知识吧!不怕你不会 ...
- 如何将 .NetFramework WebApi 按业务拆分成多个模块
在 .NetFramework 中使用 WebApi ,在不讨论 微服务 的模式下,大部分都是以层来拆分库的 : 基础设施 数据存储层 服务层 WeApi 层 一些其它的功能库 项目结构可能会像下面这 ...
- 1019 General Palindromic Number (20 分)
A number that will be the same when it is written forwards or backwards is known as a Palindromic Nu ...
- 计算机网络学习笔记NO.2 物理层
2.1 基本概念 2.1.1 物理层概念 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体. 物理层主要任务:确定与传输媒体接口有关的一些特性(定义标准) 机械特性:定 ...
- MySql 存储过程分页。
use address;drop procedure if exists `proc_s_area_code`;delimiter // #告诉mysql解释器,该段命令是否已经结束了,mysql是否 ...
- nginx产品环境安全配置-主配置文件
以下配置为产品环境的nginx基于安全和效率的主配置文件,不包含fastcgi相关配置 cat /etc/nginx/nginx.conf user nginx; worker_processes a ...