6.事务 连接池

事务
  事务介绍:
    就是一件事情,操作要不全部成功,要不全部失败。
    mysql里的事务操作
      通过一个命令(show variables like ‘autocommit‘;)
        得到 autocommit=on;意思是事务 都自动提交
        每一条sql都是一个事务
      手动事务的操作:(☆)
        start transaction; 开始事务(不管是否自动提交)
        commit;提交事务
        rollback;事务回滚
      通过以下命令,可以设置事务为手动提交
        set autocommit=off;
        注意:一旦设置手动提交后,不要使用start transaction再开启事务了,这时开启的是新事务
    java里的事务操作
      Connection接口里面的方法:☆
        void setAutoCommit(boolean autoCommet):设置事务是否自动提交
        void commit():提交事务
        void rollback():事务回滚

        Savepoint setSavePoint():设置一个还原点
        void rollback(savepoint):还原到哪个还原点

public class AccountDemo {

    public static void main(String[] args)  {

        //aaa->bbb转钱
        Connection conn=null;
        PreparedStatement ps=null;
        ResultSet rs=null;
        Savepoint p=null;

        try {
            conn=JDBCUtils.getConnection();

            //手动开启事务
            conn.setAutoCommit(false);

            //先给a减钱
            String sql="update account set money =money-? where name=?";
            ps=conn.prepareStatement(sql);
            ps.setString(1, "500");
            ps.setString(2, "aaa");
            int i=ps.executeUpdate();
            System.out.println(i);

            //设置还原点
            p=conn.setSavepoint();

            /*if(i==1){
                throw new RuntimeException();
            }*/

            //给b加钱
            sql="update account set money =money+? where name=?";
            ps=conn.prepareStatement(sql);
            ps.setString(1, "500");
            ps.setString(2, "bbb");
            i=ps.executeUpdate();
            System.out.println(i);

        } catch (Exception e) {
            e.printStackTrace();
            //回滚事务
            try {
                conn.rollback(p);
            } catch (SQLException e1) {

                e1.printStackTrace();
            }
        }finally{
            //提交事务
            try {
                conn.commit();
            } catch (SQLException e) {

                e.printStackTrace();
            }

            JDBCUtils.closeResources(conn, ps, rs);
        }

    }

}

  事务的特性:(☆)
    ACID
    原子性:atomicity 要么全部成功,要么全部失败
    一致性:consistency 事务执行之后,数据库状态与其它业务规则保持一致。例如:转账,总钱数不变
    隔离性:isolation 在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
    持久性:durability 一旦事务提交或回滚后,必须持久化到数据库中
  隔离性:
    若不考虑隔离性,会出现的问题:
      脏读:读取到别的事务没有提交的数据
      不可重复读:在一个事务中,两次查询的结果不一致(内容 update)
      虚读(幻读):在一个事务中,两次查询的结果不一致(条数,针对insert delete操作)
    数据库的隔离级别:
      read uncommitted:读未提交,最低的级别,上面的情况都可以发生
      read committed:读已提交,可以避免脏读
      repeatable read:可重复读,可以避免不可重复读
      serializable:串行化,最高的等级,可以避免所有问题。
  演示几种问题:
    设置数据库的隔离级别:
      set session transactioin isolation level 级别;
    查看当前的隔离级别:
      select @@tx_isolation;
      mysql默认的隔离级别:repeatable read☆
      oracle扩展的隔离级别:read committed☆
  安全性:
    serializable>repeatable read>read committed>read uncommitted
  效率:反之

  案例:
    转账案例
    解决service层需要传入connection参数:
    Map<Thread,Connection> map

    第一次开始事务的时候,先获取map.get(Thread.currentThread()) == ThreadLocal.get()
    获取一个connection,开启事务,最后map.put(Thread.currentThread(),connection) == ThreadLocal.set()
    在dao层可以直接使用,map.get(Thread.currentThread())就可以获取绑定的链接

  执行的流程:
    account.jsp:接收用户信息
    accountServlet:接收参数,调用service,页面的跳转
    accountService:
      1.开启事务
        conn.startTransaction() ThreadLocal作用:将当前的链接和当前的线程绑定起来
      2.开始转账
      3.一旦出现异常 获取当前线程绑定的链接调用rollBack()
      4.最后,提交事务,获取当前线程绑定的链接调用commit(),然后关闭链接,最后和当前线程解绑
    accountDao:
      转入
      转出

account.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1><font color="red">${msg }</font></h1>
	<form method="post" action="${pageContext.request.contextPath }/account">
		<table border="1">
			<tr>
				<td>汇款人:</td>
				<td><input type="text" name="fromuser"></td>
			</tr>
			<tr>
				<td>收款人:</td>
				<td><input type="text" name="touser"></td>
			</tr>
			<tr>
				<td>转账金额:</td>
				<td><input type="text" name="money"></td>
			</tr>
			<tr>
				<td colspan="2"><input type="submit"></td>
			</tr>
		</table>
	 </form>
</body>
</html>

JDBCUtil:

public class JDBCUtils_ {

	static final String DRIVERCLASSNAME;
    static final String URL;
    static final String USER;
    static final String PASSWORD;

    static{
    	/**
		 * ResourceBundle:用于加载properties文件
		 * 	 ResourceBundle bundle=ResourceBundle.getBundle(文件名称);
		 *   通过bundle的getString(key)就可以获取指定value
		 *    String url=bundle.getString("url");
		 */
    	ResourceBundle bundle=ResourceBundle.getBundle("jdbc"); //不需要后缀名
    	DRIVERCLASSNAME=bundle.getString("driverClassName");
    	URL=bundle.getString("url");
    	USER=bundle.getString("user");
    	PASSWORD=bundle.getString("password");
    }

    static{

    	try {
			Class.forName(DRIVERCLASSNAME);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

    private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();

  /**
   * 获取链接
   * @return 链接
   * @throws SQLException
   */
    public static Connection getConnection() throws SQLException{
    	//第一次开启事务,先获取
    	Connection conn=tl.get();
    	if(conn==null){
    		//创建一个
    		conn= DriverManager.getConnection(URL,USER,PASSWORD);
    		//和当前线程绑定
    		tl.set(conn);

    	}
    	return conn;
    }

    /**
     * 开启事务
     * @throws SQLException
     */
    public static void startTransaction() throws SQLException{
    	getConnection().setAutoCommit(false);
    }

    /**
     * 事务回滚
     * @throws SQLException
     */
    public static void rooBack() throws SQLException{
    	getConnection().rollback();
    }

    /**
     * 事务提交及关闭
     * @throws SQLException
     */
    public static void coommitAndClose() throws SQLException{
    	Connection conn=getConnection();
    	conn.commit();
    	conn.close();
    	tl.remove();//将链接移除
    }

    /**
     * 做增删改的时候调用
     * @param conn
     * @param st
     */
    public static void closeResources(Connection conn,Statement st){

    	if(st!=null){
    		try {
				st.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	if(conn!=null){
    		try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }

    /**
     * 做查询时调用
     * @param conn
     * @param st
     * @param rs
     */
    public static void closeResources(Connection conn,Statement st,ResultSet rs){
    	closeResources(st,rs);

    	if(conn!=null){
    		try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }

    public static void closeResources(Statement st,ResultSet rs){
    	if(rs!=null){
    		try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	if(st!=null){
    		try {
				st.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }

}

AccountServlet:

public class AccountServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/*
		 * 接收参数
		 * 调用service
		 */
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//0.设置编码
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");  

		//1.接收参数
		String fromUser=request.getParameter("fromuser");
		String toUser=request.getParameter("touser");
		String money=request.getParameter("money");

		//2.调用service
		AccountService accountService=new AccountService();
		try {
			accountService.account(fromUser, toUser, money);
		} catch (MyException e) {
			e.printStackTrace();
			//添加消息,页面跳转
			request.setAttribute("msg", e.getMessage());
			request.getRequestDispatcher("/account.jsp").forward(request, response);
			return;
		}

		//3.页面跳转
		response.getWriter().print("转账成功");
	}
}

AccountService:

public class AccountService_ {

	public void  account(String fromUser,String toUser,String money){
		//开始事务
		try {
			JDBCUtils_.startTransaction();

			AccountDao_ accountDao=new AccountDao_();
			//出
			accountDao.accountOut( fromUser, money);

			//如
			accountDao.accountIn(toUser,money);

		} catch (SQLException e) {

			e.printStackTrace();

			//回滚
			try {
				JDBCUtils_.rooBack();
			} catch (SQLException e1) {

				e1.printStackTrace();
			}
		} catch (MyException e) {

			e.printStackTrace();
		}finally{
			//提交
			try {
				JDBCUtils_.coommitAndClose();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

AccountDao:

public class AccountDao_ {

	public void accountOut(String fromUser, String money) throws MyException {
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;

		try {
			conn=JDBCUtils_.getConnection();
			String sql="upate account set money=money-? where name=?";
			ps.setString(1, money);
			ps.setString(2, fromUser);

			int i=ps.executeUpdate();
			if(i!=1){
				throw new MyException("转出失败");
			}
		} catch (SQLException e) {

			e.printStackTrace();
			try {
				JDBCUtils_.rooBack();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

		}finally{
			try {
				JDBCUtils_.coommitAndClose();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void accountIn(String toUser, String money) throws MyException, SQLException {
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;

		try {
			conn=JDBCUtils_.getConnection();
			String sql="upate account set money=money+? where name=?";
			ps.setString(1, money);
			ps.setString(2, toUser);

			int i=ps.executeUpdate();
			if(i!=1){
				throw new MyException("转入失败");
			}
		} catch (SQLException e) {

			e.printStackTrace();
			try {
				JDBCUtils_.rooBack();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}finally{
			JDBCUtils_.coommitAndClose();
		}

	}

}

Exception:

public class MyException extends Exception{

	public MyException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

	public MyException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public MyException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public MyException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}
}

  

连接池:
  连接池的优点:
    1.提高了链接的复用性
    2.节省了创建链接、销毁链接的时间,提高了性能
  规范:
    连接池都应该是DataSource的实现,datasource是一个规范,javax.sql包的一个接口
  获取链接:
    getConnection()
  关闭的时候:
    conn.close()
  常见的连接池:
    dbcp(理解):apache组织的
    c3p0(☆):c3p0
    tomcat内置的连接池(了解)
  dbcp的使用:
    1.导入jar包 commons-dbcp-1.4.jar(核心) 和commons-pool-1.5.6.jar(依赖)
    2.编写代码(两种方式)
    第一种方式:源码中配置

    第二种方式:配置文件

dbcp.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day14
username=root
password=moujinling321

DBCPDemo
public class DBCPDemo {
    public static void main(String args[]) throws Exception {
        //method1();
        method2();
    }

    private static void method2() throws Exception {
        /*
         * 方式二:配置文件
         */
        BasicDataSourceFactory factory=new BasicDataSourceFactory();
        Properties p=new Properties();
        p.load(new FileInputStream("src/dbcp.properties"));

        DataSource ds=factory.createDataSource(p); 

        Connection conn=ds.getConnection();
        String sql="select * from account limit 1";
        PreparedStatement ps=null;
        ResultSet rs=null;

        ps=conn.prepareStatement(sql);
        rs=ps.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString(1)+":"+rs.getString(2));
        }
        rs.close();
        ps.close();
        conn.close();

    }

    private static void method1() throws SQLException{
        /*
         * 方式一:源码中配置
         */
        BasicDataSource ds=new BasicDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/day14");
        ds.setUsername("root");
        ds.setPassword("moujinling321");

        Connection conn=ds.getConnection();
        String sql="select * from account";
        PreparedStatement ps=null;
        ResultSet rs=null;

        ps=conn.prepareStatement(sql);
        rs=ps.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString(1)+":"+rs.getString(2));
        }
        rs.close();
        ps.close();
        conn.close();
    }
}

  c3p0的使用:
    项目中使用
    自动回收空闲的链接
    使用步骤:
      1.导入jar包 c3p0-0.9.1.2.jar
      2.编码
      方式1:编码中编写配置(理解)
      方式2:配置文件

c3p0.properties
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/day14
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.user=root
c3p0.password=moujinling321

C3P0Demo
public class C3P0Demo {
    public static void main(String[] args) throws PropertyVetoException, SQLException {
        //method1();
        method2();
    }

    //第二种方式:配置文件(自动查找)
    private static void method2() throws SQLException {

        ComboPooledDataSource ds= new ComboPooledDataSource();

        Connection conn=ds.getConnection();
        String sql="select * from account limit 1";
        PreparedStatement ps=null;
        ResultSet rs=null;

        ps=conn.prepareStatement(sql);
        rs=ps.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString(1)+":"+rs.getString(2));
        }
        rs.close();
        ps.close();
        conn.close();

    }

    //第一种方式:源码中配置
    private static void method1() throws PropertyVetoException, SQLException {
        ComboPooledDataSource ds= new ComboPooledDataSource();
        ds.setDriverClass("com.mysql.jdbc.Driver");
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/day14");
        ds.setUser("root");
        ds.setPassword("moujinling321");

        Connection conn=ds.getConnection();
        String sql="select * from account";
        PreparedStatement ps=null;
        ResultSet rs=null;

        ps=conn.prepareStatement(sql);
        rs=ps.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString(1)+":"+rs.getString(2));
        }
        rs.close();
        ps.close();
        conn.close();
    }
}

注册要求:用户名相同不能注册

regist.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>bookStore 商城-商品信息展示</title>
	</head>
	<body>
		<!-- head 一行两列的表格-->
		<%@include file="/public/head.jsp" %>

		<!-- menu 一行一列的表格-->
		<%@include file="/public/menu.jsp" %>

		<!-- search 一行一列的表格 -->
		<div id="search">
			<table width="100%" bgcolor="#B6B684">
				<tr align="right">
					<td>
						search
						<input type="text"/>
						<input type="button" value="搜索"/>      
					</td>
				</tr>
			</table>
		</div>

		<!-- content -->
		<div id="content">
			<form action="${pageContext.request.contextPath}/regist" method="post">
				<table align="center" bgcolor="#FFFFF4" width="60%">
					<tr>
						<td>
							<h1>新会员注册<font color="red">${regist_msg }</font></h1>
							<table align="center">
								<tr>
									<td align="right" >会员邮箱:</td>
									<td>
										<input type="text" name="email"/>
									</td>
									<td align="left">
										<font color="#ff0000">${map.email_msg }</font>
									</td>
								</tr>
								<tr>
									<td align="right">会员名:</td>
									<td>
										<input type="text" name="username" class="txtinput"/>
									</td>
									<td align="left">
										<font color="#ff0000"></font>
									</td>
								</tr>
								<tr>
									<td align="right">密码:</td>
									<td>
										<input type="password" name="password" class="txtinput"/>
									</td>
									<td align="left">
										<font color="#ff0000"></font>
									</td>
								</tr>
								<tr>
									<td align="right">重复密码:</td>
									<td>
										<input type="text" name="repassword"/>
									</td>
								</tr>
								<tr>
									<td align="right">性别:</td>
									<td>
										<input type="radio" name="sex" value="男"/>男
										<input type="radio" name="sex" value="女"/>女
									</td>
									<td></td>
								</tr>
								<tr>
									<td align="right">联系电话:</td>
									<td>
										<input type="text" name="telephone"/>
									</td>
								</tr>
								<tr>
									<td align="right">个人介绍:</td>
									<td>
										<input type="textarea" name="introduce"/>
									</td>
								</tr>
							</table>
							<h1>注册校验</h1>
							<table align="center" width="80%" cellspacing="2">
								<tr>
									<td align="right">输入校验码:</td>
									<td>
										<input type="text" name="checkcode" class="txtinput"/>
									</td>
									<td>${requestScope["code.msg"] }</td> <!-- code.msg,单独不可以写进去,.表示get。用域对象表示出来 -->
								</tr>
								<tr>
									<td> </td>
									<td colspan="2">
										<img src="${pageContext.request.contextPath }/code" id="imgId" alt="验证码" class="txtinput" style="height:30px"/>
										<a href="javascript:void(0)" onclick="changeCode()">看不清?换一张</a>
										<!-- 表示这个链接不做跳转动作,执行onClick事件。 -->
									</td>
								</tr>
								<tr>
									<td align="center" colspan="3">
										<input value="同意并提交" style="background:orange;height:30px;width:100px;text-align:center;" type="submit"/>
									</td>
								</tr>
							</table>
						</td>
					</tr>
				</table>
			</form>

		</div>

		<!-- foot 两行两列的表格-->
		<div id="foot">
			<table width="100%" bgcolor="#EFEEDC">
				<tr>
					<td rowspan="2" align="center">
						<img src="images/case1/logo.png" alt="图书商城"/>
					</td>
					<td>CONTACT US</td>
				</tr>
				<tr>
					<td>
						copyright 2008&copyrightBookStore All Rights RESERVED
					</td>
				</tr>
			</table>
		</div>

		<table width="100%">
			<tr>
				<td></td>
			</tr>
		</table>
	</body>
<script type="text/javascript">
	function changeCode(){
		var imgObj=document.getElementById("imgId");
		imgObj.src="${pageContext.request.contextPath}/code?i="+Math.random();
	}
</script>

</html>

  RegistServlet

package web.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import domain.User;
import exception.UserRegistException;
import service.UserService;

public class RegistServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		request.setCharacterEncoding("utf-8");

		/*
		 * 作用:首先判断验证码
		 * 	若验证码不一致,返回错误信息(regist.jsp) 提示信息(验证码错误) request
		 * 	验证码一致,封装参数,调用userservice
		 */

		//1.获取验证码
		//1.1获取页面上验证码
		String code=request.getParameter("checkcode");

		//1.2获取session域中的验证码
		String sessionCode=(String) request.getSession().getAttribute("session_code");
		request.getSession().removeAttribute("session_code"); //验证码一次性

		//2.判断验证码
		//输入验证码不正确
		if(!sessionCode.equalsIgnoreCase(code)){
			//加入错误信息,页面跳转
			request.setAttribute("code.msg", "验证码输入错误");
			request.getRequestDispatcher("/regist.jsp").forward(request,response);
			return;
		}

		//3.获取参数
		User user=new User();
		try {
			BeanUtils.populate(user, request.getParameterMap());
		} catch (IllegalAccessException | InvocationTargetException e) {

			e.printStackTrace();
		}
		//3.1数据校验
		//验证邮件
		Map<String,String> map=user.validate();
		if(map!=null && map.size()>0){
			//有错误信息
			request.setAttribute("map", map);
			request.getRequestDispatcher("/regist.jsp").forward(request, response);
			return;
		}

		//4.调用userservice
		UserService userService=new UserService();
		//可能抛自定义异常
		try {
			userService.regist(user);
		} catch (UserRegistException e) {
			e.printStackTrace();
			//有异常,添加错误信息,跳转到注册页面
			request.setAttribute("regist_msg", e.getMessage());
			request.getRequestDispatcher("/regist.jsp").forward(request, response);
		}

		//5.页面跳转,提示信息
		//5.1将user放到session中
		request.getSession().setAttribute("user", user);

		//5.2提示信息 页面跳转
		response.setHeader("refresh", "3;url="+request.getContextPath()+"/success.jsp");
		response.getWriter().print("注册成功,3秒之后跳转到首页!");

	}
}

  UserService

public class UserService {
	UserDaoImpl userDao=new UserDaoImpl();
	/**
	 * 用户注册
	 * @param user 用户信息
	 * @throws UserRegistException
	 */
	public void regist(User user) throws UserRegistException  {

		try {
			//开启事务
			DataSourceUtils.startTransaction();

			/*
			 * 首先判断数据库中有没有同名的
			 * 	若有,返回true,不能注册,提示信息
			 * 	若无,可以添加
			 */
			boolean flag=userDao.findUserByUsername(user);
			if(!flag){//flag=false

				//调用userdao的adduser方法
				userDao.addUser(user);
			}else{
				throw new UserRegistException("该用户名已被占用");
			}
		} catch (SQLException e) {

			e.printStackTrace();

			try {
				DataSourceUtils.rollBack();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			throw new UserRegistException("网络异常!!");
		}finally{
			//提交事务
			try {
				DataSourceUtils.commitAndClose();
			} catch (SQLException e) {

				e.printStackTrace();
			}
		}

	}

}

  UserDao

public class UserDaoImpl implements UserDao{
	/**
	 * 添加用户
	 * @param user 用户信息
	 * @throws UserRegistException
	 * @throws SQLException
	 */
	public void addUser(User user) throws UserRegistException {
		//使用JDBC操作数据库
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;

		try {
			conn=DataSourceUtils.getConnection();

			//编写sql
			//username,password,sex,telephone,email,introduce
			String sql="insert into user values(null,?,?,?,?,?,?)";

			//创建语句执行者
			ps=conn.prepareStatement(sql);
			//设置参数
			ps.setString(1, user.getUsername());
			ps.setString(2, user.getPassword());
			ps.setString(3, user.getSex());
			ps.setString(4, user.getTelephone());
			ps.setString(5, user.getEmail());
			ps.setString(6, user.getIntroduce());
			//执行sql
			int i=ps.executeUpdate();
			if(i==0){
				throw new UserRegistException("注册失败");
			}
			//处理结果
			System.out.println(i);
		} catch (SQLException e) {
			// 数据库异常
			e.printStackTrace();
			throw new UserRegistException("网络异常,请稍后再试");
		}finally{
			//释放资源
			DataSourceUtils.closeResources(ps, rs);
		}
	}

	/**
	 * 通过用户名查找用户
	 * 	若存在返回true
	 * 	若不存在返回false
	 */
	public boolean findUserByUsername(User user) {

		//使用JDBC操作数据库
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;

		try {
			conn=DataSourceUtils.getConnection();
			String sql="select * from user where username=? limit 1";
			ps=conn.prepareStatement(sql);
			ps.setString(1, user.getUsername());
			rs=ps.executeQuery();
			return rs.next();
		} catch (SQLException e) {

			e.printStackTrace();
		}finally{
			DataSourceUtils.closeResources(ps, rs);
		}
		return false;
	}
}

  User

public class User {
	private Integer id;
	private String email;
	private String username;
	private String password;
	private String sex;
	private String introduce;
	private String telephone;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getIntroduce() {
		return introduce;
	}
	public void setIntroduce(String introduce) {
		this.introduce = introduce;
	}
	public String getTelephone() {
		return telephone;
	}
	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}
	public User(Integer id, String email, String username, String password, String sex, String introduce,
			String telephone) {
		super();
		this.id = id;
		this.email = email;
		this.username = username;
		this.password = password;
		this.sex = sex;
		this.introduce = introduce;
		this.telephone = telephone;
	}
	public User() {
		super();
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", email=" + email + ", username=" + username + ", password=" + password + ", sex="
				+ sex + ", introduce=" + introduce + ", telephone=" + telephone + "]";
	}
	public Map<String, String> validate() {
		//创建Map
		Map<String,String> map=new HashMap();

		//验证邮箱
		/*
		 * 首先验证邮箱是否为空
		 * 	若为空,提示邮箱不能为空
		 * 	若不为空,继续验证邮箱是否符合格式
		 * 		若不符合,提示邮箱格式不争取
		 *
		 */
		if(isNull(email)){
			map.put("email_msg", "邮箱不能为空");
		}else if(!checkEmail(email)){
			map.put("email_msg", "邮箱格式不合法");
		}

		return map;
	}

	/**
	 * 判断邮箱格式
	 * 	若符合格式,返回true
	 * 	若不符合格式,返回false
	 * @param value
	 * @return bolean
	 */
	private boolean checkEmail(String value) {
		if(value==null){
			return false;
		}
		//[email protected]
		String reg="^\\[email protected]\\w+(\\.\\w+)+$";
		return value.matches(reg);
	}
	/**
	 * 验证是否为空
	 * 	若为空返回Null
	 * 	若不为空返回false
	 * @param value
	 * @return boolean
	 */
	private boolean isNull(String value) {
		//^\s*&
		if(value==null){
			return true;
		}
		return value.matches("^\\s*$");
	}

}

  

原文地址:https://www.cnblogs.com/syj1993/p/8440164.html

时间: 2024-10-03 23:01:15

6.事务 连接池的相关文章

day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)

day18总结 今日思维导图: 今日内容 事务 连接池 ThreadLocal BaseServlet自定义Servlet父类(只要求会用,不要求会写) DBUtils à commons-dbutils ? 事务 ? 事务的四大特性:ACID: mysql中操作事务 jdbc中操作事务 ? ? ? 事务概述 为了方便演示事务,我们需要创建一个account表: CREATE TABLE account( ????id INT PRIMARY KEY AUTO_INCREMENT, ????NA

Java实战之04JavaWeb-05事务和连接池

一.事务部分 1.事务的简介 做一件事情,这个一件事情中有多个组成单元,这个多个组成单元要不同时成功,要不同时失败.A账户转给B账户钱,将A账户转出钱的操作与B账户转入钱的操作绑定到一个事务中,要不这两个动作同时成功,代表这次转账成功,要不就两个动作同时失败,代表这次转账失败. 2.mysql的事务控制 mysql默认事务是自动提交的,一条sql是一个事务 手动开启事务:start transaction 当手动开启事务后,数据库默认的事务的自动提交暂时失效 提交事务:commit 提交事务到开

SpringMVC+Spring+Mybatis整合,使用druid连接池,声明式事务,maven配置

一直对springmvc和mybatis挺怀念的,最近想自己再搭建下框架,然后写点什么. 暂时没有整合缓存,druid也没有做ip地址的过滤.Spring的AOP简单配置了下,也还没具体弄,不知道能不能用,log也不知道能不能用,`(*∩_∩*)′哈哈,有点不负责任...... 直接上代码: 使用的eclipse和eclipse自带的maven,参考了网上的资料,有些代码是拷贝的,不过都自己测试过了.嗯,可以跑起来... 先上项目结构: 新建maven项目,选择web,然后配置pom: <pro

JAVAWEB开发之事务详解(mysql与JDBC下使用方法、事务的特性、锁机制)和连接池的详细使用(dbcp以d3p0)

事务简介 事务的概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功 在开发中,有事务的存在,可以保证数据的完整性. 注意:数据库默认事务是自动提交的,也就是发一条SQL 就执行一条.如果想多条SQL语句放在一个事务中执行,需要添加事务有关的语句. 如何开启事务? 事务的操作方式: 创建表: create table account( id int primary key auto_increment, name varchar(20), money double

连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法

本文出处:http://www.cnblogs.com/wy123/p/6110349.html 之前遇到过这么一种情况: 连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持续较长时间,有时间持续时间较短,没有什么规律.  之后分析相关存储过程和代码写法,发现是存储过程中开启了事务,而应用程序在调用存储过程发生异常之后没有进行特别的处理(提交或者回滚),  那么在执行方法发生异常之后,连接关闭了,但是数据库中遗留有活动事务(dbcc opentran对应的Session

Spring Boot1.5.4 连接池 和 事务

原文:https://github.com/x113773/testall/issues/10 默认连接池---spring Boot中默认支持的连接池有Tomcat.HikariCP .DBCP .DBCP2,以下摘自[官方文档](http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-configure-datasource):> Production database

JavaWeb系列之十三(jdbc事务与连接池)

 1.事务:表示一组操作要么都成功,有一个失败,所有操作都会失败. 在mysql要使用事务,就要先开启事务,语句start transaction,提交事务:commit 回滚事务:rollback. 转账: 2.jdbc事务的操作 (1)操作事务的方法 setAutoCommit(boolean autoCommit) 设置事务的提交方式,默认自动提交,设置为fals不会提交 提交事务commit() 回滚事务rollback() 使用jdbc来完成转账 小金跟小李接一千 (2)设置事务的

网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别

1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2次. >强烈依赖数据库的驱动jar 解决办法: Class.forName("com.mysql.jdbc.Driver"); 1.1.2 API详解:java.sql.Statement接口: 操作sql语句,并返回相应结果 String sql = "某SQL语句&qu

连接池+事务

事务的四个特性: 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样.也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位.  2.一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 .比如A向B转账,不可能A扣了钱,B却没收到. 3.隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间