一.项目架构

注:删除了原有的数据库工具,添加了c3p0数据库工具类,添加了c3p0的配置文件,修改了Dao类以及servlet类
二.修改或添加的类
1.C3p0Helper(暂时不了解事务回滚之类的怎么用或者有什么用,只用了连接和关闭)
package helper;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Helper {
private static String configName = "mysql";
//如果无参,则使用c3p0-config.xml中的default-config,该处使用mysql的配置
private static DataSource ds = new ComboPooledDataSource(configName);
/**
* 它为null表示没有事务
* 它不为null表示有事务
* 当开启事务时,需要给它赋值
* 当结束事务时,需要给它赋值为null
* 并且在开启事务时,让dao的多个方法共享这个Connection
*/
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
public static DataSource getDataSource() {
return ds;
}
/**
* dao使用本方法来获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
/*
* 如果有事务,返回当前事务的con
* 如果没有事务,通过连接池返回新的con
*/
Connection con = tl.get();//获取当前线程的事务连接
if(con != null)
return con;
return ds.getConnection();
}
/**
* 开启事务
* @throws SQLException
*/
public static void beginTransaction() throws SQLException {
Connection con = tl.get();//获取当前线程的事务连接
if(con != null) throw new SQLException("已经开启了事务,不能重复开启!");
con = ds.getConnection();//给con赋值,表示开启了事务
con.setAutoCommit(false);//设置为手动提交
tl.set(con);//把当前事务连接放到tl中
}
/**
* 提交事务
* @throws SQLException
*/
public static void commitTransaction() throws SQLException {
Connection con = tl.get();//获取当前线程的事务连接
if(con == null) throw new SQLException("没有事务不能提交!");
con.commit();//提交事务
con.close();//关闭连接
con = null;//表示事务结束!
tl.remove();
}
/**
* 回滚事务
* @throws SQLException
*/
public static void rollbackTransaction() throws SQLException {
Connection con = tl.get();//获取当前线程的事务连接
if(con == null) throw new SQLException("没有事务不能回滚!");
con.rollback();
con.close();
con = null;
tl.remove();
}
/**
* 释放Connection
* @param con
* @throws SQLException
*/
public static void releaseConnection(Connection connection) throws SQLException {
Connection con = tl.get();//获取当前线程的事务连接
if(connection != con) {//如果参数连接,与当前事务连接不同,说明这个连接不是当前事务,可以关闭!
if(connection != null &&!connection.isClosed()) {//如果参数连接没有关闭,关闭之!
connection.close();
}
}
}
}
2.UserDao
package dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import common.User;
import helper.C3p0Helper;
public class UserDao {
/**
* 查询所有用户信息
* @return
* @throws SQLException
*/
public List<User> getAllUser() throws SQLException{
List<User> list = new ArrayList<User>();
Connection conn = C3p0Helper.getConnection();//连接数据库
String sql = "select * from user";
try {
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rst = pst.executeQuery();
while (rst.next()) {
User user = new User();
user.setId(rst.getInt("id"));
user.setName(rst.getString("name"));
user.setAge(rst.getInt("age"));
list.add(user);
}
rst.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
C3p0Helper.releaseConnection(conn);
}
return list;
}
/**
* 添加用户
* @param user
* @return
* @throws SQLException
*/
public boolean addUser(User user) throws SQLException{
String sql = "INSERT INTO `user`(`name`,`age`) VALUES (?,?)";
Connection conn = C3p0Helper.getConnection();
try {
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1, user.getName());
pst.setInt(2, user.getAge());
int count = pst.executeUpdate();
pst.close();
return count>0?true:false;
} catch (SQLException e) {
e.printStackTrace();
}finally {
C3p0Helper.releaseConnection(conn);
}
return false;
}
/**
* 修改用户信息
* @param user
* @return
* @throws SQLException
*/
public boolean updateUser(User user) throws SQLException{
String sql = "UPDATE `user` SET `name`=?,`age`=? WHERE `id` = ?";
Connection conn = C3p0Helper.getConnection();
try {
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1, user.getName());
pst.setInt(2, user.getAge());
pst.setInt(3, user.getId());
int count = pst.executeUpdate();
pst.close();
return count>0?true:false;
} catch (SQLException e) {
e.printStackTrace();
}finally {
C3p0Helper.releaseConnection(conn);
}
return false;
}
/**
* 删除用户
* @param id
* @return
* @throws SQLException
*/
public boolean deleteUser(int id) throws SQLException{
String sql = "delete from user where id = ?";
Connection conn = C3p0Helper.getConnection();
try {
PreparedStatement pst = conn.prepareStatement(sql);
pst.setInt(1, id);
int count = pst.executeUpdate();
pst.close();
return count>0?true:false;
} catch (SQLException e) {
e.printStackTrace();
}finally {
C3p0Helper.releaseConnection(conn);
}
return false;
}
/**
* 根据ID进行查询用户
* @param id
* @return
* @throws SQLException
*/
public User selectUserById(int id) throws SQLException{
Connection conn = C3p0Helper.getConnection();
String sql = "select * from user where id = "+id;
User user = null;
try {
PreparedStatement pst = conn.prepareStatement(sql);
ResultSet rst = pst.executeQuery();
while (rst.next()) {
user = new User();
user.setId(rst.getInt("id"));
user.setName(rst.getString("name"));
user.setAge(rst.getInt("age"));
}
rst.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
C3p0Helper.releaseConnection(conn);
}
return user;
}
}
3.Servlet
package servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import common.User;
import dao.UserDao;
public class AddServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException { this.doPost(req, resp); }
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name = req.getParameter("name");
Integer age = Integer.valueOf(req.getParameter("age"));
User user = new User();//创建user对象
user.setName(name);
user.setAge(age);
UserDao dao = new UserDao();
try {
dao.addUser(user);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//添加到数据库中
req.getRequestDispatcher("list").forward(req, resp);
}
// @Override
// protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// String name = req.getParameter("name");
// Integer age = Integer.valueOf(req.getParameter("age"));
// System.out.println("name:"+name+" 111111111 age:"+age);
// User user = new User();//创建user对象
// user.setName(name);
// user.setAge(age);
// UserDao dao = new UserDao();
// dao.addUser(user);//添加到数据库中
// req.getRequestDispatcher("list").forward(req, resp);
// }
}
package servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.UserDao;
public class DeleteServlet extends HttpServlet{
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String idStr = req.getParameter("id"); // 删除数据的ID,根据ID删除
if (idStr != null && !idStr.equals("")) {
int id = Integer.valueOf(idStr);
UserDao dao = new UserDao();
try {
dao.deleteUser(id);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
req.getRequestDispatcher("list").forward(req, resp);
}
}
package servlet;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import common.User;
import dao.UserDao;
@WebServlet("/list")
public class ListServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
UserDao dao = new UserDao();
try {
List<User> list = dao.getAllUser();
System.out.println("dao:"+dao+" 111111111 list:"+list);
req.setAttribute("userInfoList", list);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
req.getRequestDispatcher("list.jsp").forward(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
package servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import common.User;
import dao.UserDao;
public class UpdateServlet extends HttpServlet {
/**
* 查询到选中ID的值所对应的数据
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String idStr = req.getParameter("id");
if (idStr != null && !idStr.equals("")) {
int id = Integer.valueOf(idStr);
UserDao dao = new UserDao();
try {
User user = dao.selectUserById(id);
req.setAttribute("user", user);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
req.getRequestDispatcher("update.jsp").forward(req, resp);
}
/**
* 根据此ID对数据的值进行修改
*/
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String idStr = req.getParameter("id");
if (idStr != null && !idStr.equals("")) {
int id = Integer.valueOf(idStr);
String name = req.getParameter("name");
Integer age = Integer.valueOf(req.getParameter("age"));
User user = new User();
user.setId(id);
user.setName(name);
user.setAge(age);
UserDao dao = new UserDao();
try {
dao.updateUser(user);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
req.getRequestDispatcher("list").forward(req, resp);
}
}
4.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- This is default config! -->
<default-config>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<!-- This is my config for mysql-->
<named-config name="mysql">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- 设置字符集和时区 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/my-db?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false</property>
<property name="user">root</property>
<property name="password">Pa33w0rd</property>
<!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3-->
<property name="initialPoolSize">6</property>
<!--最大空闲时间,超过该秒数未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->
<property name="maxIdleTime">20</property>
<!--连接池中保留的最大连接数。默认值: 15 -->
<property name="maxPoolSize">20</property>
<!-- 连接池中保留的最小连接数,默认为:3-->
<property name="minPoolSize">5</property>
<!-- 当连接池连接耗尽时,客户端调用getConnection()后等待获取新连接的时间,
超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 0 -->
<property name="checkoutTimeout">3000</property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->
<property name="acquireIncrement">5</property>
<!--定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次-->
<property name="acquireRetryAttempts">5</property>
<!--重新尝试的时间间隔,默认为:1000毫秒-->
<property name="acquireRetryDelay">1000</property>
<!--关闭连接时,是否提交未提交的事务,默认为false,即关闭连接,回滚未提交的事务 -->
<property name="autoCommitOnClose">false</property>
<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个
参数那么属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,
它将只供c3p0测试使用。默认值: null -->
<property name="automaticTestTable">Test</property>
<!--如果为false,则获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常,
但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。
如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--每60秒检查所有连接池中的空闲连接。默认值: 0,不检查 -->
<property name="idleConnectionTestPeriod">60</property>
<!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。
默认值: 0 -->
<!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。
但由于预缓存的statements
属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->
<property name="maxStatements">200</property>
<property name="maxStatementsPerConnection">100</property>
</named-config>
</c3p0-config>