Java_通过PreparedStatement往MySql数据库插入中文出现'?'乱码问题解决;

时间:2022-02-17 06:43:30

前言: 在Java中,通过PreparedStatement往MySql数据库插入中文出现'?'乱码问题,困扰好久!通过九九八十一难后,终于得到解决!其实,说起来不难理解, 我们知道,在java中经常通过jdbc连接MySQL数据库,如果我们在连接url的末尾加上?characterEncoding=gbk,明确指定编码,问题就迎刃而解。下面是示例(通过测试):


=>RequestListener.java

package lee;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

import java.sql.*;

@WebListener
public class RequestListener implements ServletRequestListener {
// 当用户请求到达、被初始化时触发该方法
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();

HttpSession session = request.getSession();
String sessionId = session.getId();// 获取session ID;
String ip = request.getRemoteAddr();// 获取访问的IP;
String page = request.getRequestURI();// 正在访问的页面;
String user = (String)session.getAttribute("user");
user = (user == null) ? "游23客" : user;// 未登录用户当游客处理;

try {
// 特别说明数据库url中尾部添加?characterEncoding=gbk是解决java PreparedStatement 插入中文时出现的"?"乱码;
DbDao dd = new DbDao(
"com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/online_inf?characterEncoding=gbk",
"dbuser", "123456");
ResultSet rs = dd.query(
"select * from online_inf where session_id=?", true, sessionId);

// 如果该用户对应的session ID存在,表明是旧的会话
if (rs.next()) {
// 更新记录
rs.updateString(4, page);
rs.updateLong(5, System.currentTimeMillis());
rs.updateRow();
rs.close();
} else {
// 插入该用户的在线信息
dd.insert("insert into online_inf values(? , ? , ? , ? , ?)",
sessionId, user, ip, page, System.currentTimeMillis());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}

// 当用户请求结束、被销毁时触发该方法
public void requestDestroyed(ServletRequestEvent sre) {
}
}

=>OnlineListener.java

package lee;

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

import java.sql.*;
import java.awt.event.*;

@WebListener
public class OnlineListener implements ServletContextListener {
// 超过该时间(10分钟)没有访问本站即认为用户已经离线
public final int MAX_MILLIS = 10 * 60 * 1000;

// 应用启动时触发该方法
public void contextInitialized(ServletContextEvent sce) {
// 每5秒检查一次
new javax.swing.Timer(1000 * 5, new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
// 特别说明数据库url中尾部添加?characterEncoding=gbk是解决java PreparedStatement 插入中文时出现的"?"乱码;
DbDao dd = new DbDao(
"com.mysql.jdbc.Driver",
"jdbc:mysql://localhost:3306/online_inf?characterEncoding=gbk",
"dbuser", "123456");

ResultSet rs = dd.query("select * from online_inf", false);
StringBuffer beRemove = new StringBuffer("(");
while (rs.next()) {
// 如果距离上次访问时间超过了指定时间
if ((System.currentTimeMillis() - rs.getLong(5)) > MAX_MILLIS) {
// 将需要被删除的session ID添加进来
beRemove.append("'");
beRemove.append(rs.getString(1));
beRemove.append("' , ");
}
}
// 有需要删除的记录
if (beRemove.length() > 3) {
beRemove.setLength(beRemove.length() - 3);
beRemove.append(")");
// 删除所有“超过指定时间未重新请求的记录”
dd.modify("delete from online_inf where session_id in "+ beRemove.toString());
}
dd.closeConn();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}

public void contextDestroyed(ServletContextEvent sce) {
}
}

=>DbDao.java

package lee;

import java.sql.*;

public class DbDao {
private Connection conn;
private String driver;
private String url;
private String username;
private String pass;

public DbDao() {
}

public DbDao(String driver, String url, String username, String pass) {
this.driver = driver;
this.url = url;
this.username = username;
this.pass = pass;
}

// 下面是各个成员属性的setter和getter方法
public void setDriver(String driver) {
this.driver = driver;
}

public void setUrl(String url) {
this.url = url;
}

public void setUsername(String username) {
this.username = username;
}

public void setPass(String pass) {
this.pass = pass;
}

public String getDriver() {
return (this.driver);
}

public String getUrl() {
return (this.url);
}

public String getUsername() {
return (this.username);
}

public String getPass() {
return (this.pass);
}

// 获取数据库连接
public Connection getConnection() throws Exception {
if (conn == null) {
Class.forName(this.driver);
conn = DriverManager.getConnection(url, username, this.pass);
}
return conn;
}

// 插入记录
public boolean insert(String sql, Object... args) throws Exception {
PreparedStatement pstmt = getConnection().prepareStatement(sql);

for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
}

if (pstmt.executeUpdate() != 1) {
return false;
}

pstmt.close();
return true;
}

// 执行查询
public ResultSet query(String sql, boolean updatable, Object... args)
throws Exception {
PreparedStatement pstmt = null;
if (updatable) {
// 创建可更新的PreparedStatement
pstmt = getConnection().prepareStatement(sql,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
} else {
pstmt = getConnection().prepareStatement(sql);
}
for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
}
return pstmt.executeQuery();
}

// 执行修改
public void modify(String sql, Object... args) throws Exception {
PreparedStatement pstmt = getConnection().prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pstmt.setObject(i + 1, args[i]);
}
pstmt.executeUpdate();
pstmt.close();
}

// 关闭数据库连接的方法
public void closeConn() throws Exception {
if (conn != null && !conn.isClosed()) {
conn.close();
}
}
}

特别说明:如果能帮助到您,请您留下点滴痕迹,让我知道我的存在是有意义的;如果不能帮助到您,请接受我的歉意;(示例下载)