summarize
事务开启:只有两条路,要么回滚,要么提交。开启事务(start transaction)后,到回滚(rollback)。中间的所有操作都是无效数据库,cmd里面显示的都是在内存里,没有真正进入表,从开启事务到 提交commit ; 中间所有SQL操作才有效
一、事务概述
1.什么是事务
一件事情有n个组成单元 要不这n个组成单元同时成功 要不n个单元就同时失败
就是将n个组成单元放到一个事务中
2.mysql的事务
默认的事务:一条sql语句就是一个事务 默认就开启事务并提交事务
手动事务:
1)显示的开启一个事务:start transaction
2)事务提交:commit代表从开启事务到事务提交 中间的所有的sql都认为有效 真正的更新数据库
3)事务的回滚:rollback 代表事务的回滚 从开启事务到事务回滚 中间的所有的 sql操作都认为无效数据库没有被更新
开启事务后
查询的所有命令都只是写在内存里,只有提交commit后 才会写入表内,rollback个人理解为清屏
一、JDBC事务操作
默认:自动事务:
执行sql语句:executeUpdate() ---- 每执行一次executeUpdate方法 代表 事务自动提交
通过jdbc的API手动事务:
开启事务:conn.setAutoComnmit(false);(默认:true)
提交。。:conn.commit();
回滚。。:conn.rollback();
注意:控制事务的connnection必须是同一个
执行sql的connection与开启事务的connnection必须是同一个才能对事务进行控制
建个Java项目 导包
package com.oracle.demo01; //事务 import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import com.oracle.tools.JDBCUtils; public class Demo01 { public static void main(String[] args) { // 获取连接 Connection conn = JDBCUtils.getConn(); Statement sta = null; String sql = "insert into account(aname,money) values('wangwu',1000)"; // 手动开启事务 try { sta = conn.createStatement();// 用statement 直接可以传值,不用占位 // 执行SQL前 手动开启事务 conn.setAutoCommit(false);// 手动开启设置 sta.executeUpdate(sql); } catch (SQLException e) { // 回滚 try { conn.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // TODO Auto-generated catch block e.printStackTrace(); } finally { // 注意位置 try { // 提交事务 conn.commit(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
需要注意:
Statement用于将SQL语句发送到数据库中,有三种statement对象,它们都作为在给定连接执行SQL语句的包容器
statement、PreparedStatement(Statement 的子类)、CallableStatement(Statement的孙子),这爷仨都专用于发送特定类型SQL语句
①Statement:执行不带参的简单SQL,PreparedStatement执行
②PreparedStatement:执行带或不带IN参数预编译SQL
③CallableStatement:执行对数据库存储过程的调用
Statement接口提供执行语句和获取结果方法,PreparedStatement接口添加处理IN参数方法,CallableStatement添加OUT参数方法
一、DBUtils事务操作
1.QueryRunner
有参构造:QueryRunner runner = new QueryRunner(DataSource dataSource);
有参构造将数据源(连接池)作为参数传入QueryRunner,QueryRunner会从连 接池中获得一个数据库连接资源操作数据库,所以直接使用无Connection参数 的update方法即可操作数据库
无参构造:QueryRunner runner = new QueryRunner();
无参的构造没有将数据源(连接池)作为参数传入QueryRunner,那么我们在使 用QueryRunner对象操作数据库时要使用有Connection参数的方法
我们学习无参构造:有参无法保证connection唯一性,所以需要无参构造,并手动获取连接
代码 展示 新建个tool
package com.oracle.tools; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; public class MyDBUtils { public static final String DRIVER = "com.mysql.jdbc.Driver"; public static final String URL = "jdbc:mysql://localhost:3306/java0603?useUnicode=true&characterEncoding=UTF-8"; public static final String USERNAME = "root"; public static final String PASSWORD = "123456"; /* * 创建连接池BasicDataSource */ public static BasicDataSource dataSource = new BasicDataSource(); //静态代码块(优先只执行一次) static { //对连接池对象 进行基本的配置 dataSource.setDriverClassName(DRIVER); // 这是要连接的数据库的驱动 dataSource.setUrl(URL); //指定要连接的数据库地址 dataSource.setUsername(USERNAME); //指定要连接数据的用户名 dataSource.setPassword(PASSWORD); //指定要连接数据的密码 } /* * 返回连接池对象 */ public static DataSource getDataSource(){ return dataSource; } // 返回一个连接对象 public static Connection getConn(){ Connection conn=null; try { conn=dataSource.getConnection(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return conn; } } -------------------------------------------------- package com.oracle.demo01; //无参构造QueryRunner 事务 import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.dbutils.QueryRunner; import com.oracle.tools.MyDBUtils; public class Demo02 { public static void main(String[] args) { // 创建queryrunner对象 QueryRunner qr=new QueryRunner(); // 获取连接对象 Connection conn=MyDBUtils.getConn(); String sql="update account set money=money-? where aname=?"; try { // 开启事务 conn.setAutoCommit(false);//手动开启 qr.update(conn,sql,100,"zhangsan");//更改-100 } catch (SQLException e) { // 回滚事务 try { conn.rollback();//把回滚写到try里面,上面代码已有错误就会自动回到开启事务 } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // TODO Auto-generated catch block e.printStackTrace(); }finally{ //不管对错,上面代码只要是对的,在这里就会执行 // 提交事务 try { conn.commit(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
转账项目,建个dynamic
导包
新建jsp页面 transfer.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> <!-- 用el表达式 --> <form action="${pageContext.request.contextPath }/TransServlet" method="post"> 转出账户:<input type="text" name="out"><br> 转入账户:<input type="text" name="in"><br> 转出金额:<input type="text" name="money"><br> <input type="submit" name="确认"><br> </form> </body> </html>
package com.oracle.web; //获取文本框三个值 import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.oracle.service.AccountService; public class TransServlet extends HttpServlet { private AccountService accountService=new AccountService(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 解决中文乱码 request.setCharacterEncoding("UTF-8"); // 获取转出账户 String out=request.getParameter("out"); // 获取转入账户 String in=request.getParameter("in"); // 获取金额 从前台获取的任何数据类型 都是 String String moneyStr=request.getParameter("money"); // 将字符串金额转为double double money=Double.parseDouble(moneyStr);//将字符串转double 用parseDouble // 调用service层转账方法 boolean flag=accountService.transfer(out, in, money); // 解决response乱码 response.setContentType("text/htm;charset=utf-8"); if(flag){ //判断 response.getWriter().write("转账成功"); }else{ response.getWriter().write("转账失败"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } --------------------------------- package com.oracle.Dao; //用QueryRunner方法写dao层 import java.sql.Connection; import java.sql.SQLException; import org.apache.commons.dbutils.QueryRunner; import com.oracle.tools.MyDBUtils; public class AccountDao { // 转出 public void Moneyout(Connection conn,String out,double money) throws SQLException{ // 创建QueryRunner对象 QueryRunner qr=new QueryRunner(); String sql="update account set money=money-? where aname=?"; qr.update(conn,sql,money,out); } //转入 public void Moneyin(Connection conn,String in,double money) throws SQLException{ // 创建QueryRunner对象 QueryRunner qr=new QueryRunner(); String sql="update account set money=money+? where aname=?"; qr.update(conn,sql,money,in); } } ------------------------------ package com.oracle.service; import java.sql.Connection; import java.sql.SQLException; import com.oracle.Dao.AccountDao; import com.oracle.tools.MyDBUtils; public class AccountService { private AccountDao accountDao=new AccountDao(); // 转账 public boolean transfer(String out,String in,double money){ // 定义变量 boolean flag=true; // 获取Conn连接对象 Connection conn=MyDBUtils.getConn(); // 调dao层方法 try { accountDao.Moneyin(conn, out, money); } catch (SQLException e2) { // TODO Auto-generated catch block e2.printStackTrace(); } try { // 开启事务 conn.setAutoCommit(false); accountDao.Moneyin(conn,out, money); accountDao.Moneyin(conn,in, money); } catch (SQLException e) { flag=false; try {
// 回滚:当try出现异常后会执行catch,然后回滚到开启事务之前 conn.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); }finally{ // 提交 try { conn.commit(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return flag; } }
商品管理页面的 增删改查
先去分析JSP页面的内容,在逐步去实现功能所需要的Servlet
商品展示 新建 AdminProductListServlet
package com.oracle.web; // 查 import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.oracle.domain.Category; import com.oracle.domain.Product; import com.oracle.service.CategoryService; import com.oracle.service.ProductService; public class AdminProductListServlet extends HttpServlet { private CategoryService categoryService=new CategoryService(); // 后台的商品列表页面 private ProductService productService = new ProductService(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取商品列表 List<Product> list = productService.getAll(); // 获取所有分类List List<Category> arr=categoryService.getCategory(); // 向域中存list request.setAttribute("ProductList", list); request.setAttribute("CategoryList", arr); // 请求转发 request.getRequestDispatcher("/admin/product/list.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
修改admin/left.jsp
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <title>菜单</title> 6 <link href="${pageContext.request.contextPath}/css/left.css" 7 rel="stylesheet" type="text/css" /> 8 <link rel="StyleSheet" 9 href="${pageContext.request.contextPath}/css/dtree.css" type="text/css" /> 10 </head> 11 <body> 12 <table width="100" border="0" cellspacing="0" cellpadding="0"> 13 <tr> 14 <td height="12"></td> 15 </tr> 16 </table> 17 <table width="100%" border="0"> 18 <tr> 19 <td> 20 <div class="dtree"> 21 22 <a href="javascript: d.openAll();">展开所有</a> | <a 23 href="javascript: d.closeAll();">关闭所有</a> 24 25 <script type="text/javascript" 26 src="${pageContext.request.contextPath}/js/dtree.js"></script> 27 <script type="text/javascript"> 28 d = new dTree('d'); 29 d.add('01', -1, '系统菜单树'); 30 d.add('0102', '01', '分类管理', '', '', 'mainFrame'); 31 d 32 .add( 33 '010201', 34 '0102', 35 '分类管理', 36 '${pageContext.request.contextPath}/admin/category/list.jsp', 37 '', 'mainFrame'); 38 d.add('0104', '01', '商品管理'); 39 d 40 .add( 41 '010401', 42 '0104', 43 '商品管理', 44 '${pageContext.request.contextPath}/AdminProductListServlet', 45 '', 'mainFrame'); 46 document.write(d); 47 </script> 48 </div> 49 </td> 50 </tr> 51 </table> 52 </body> 53 </html>
在修改 product/list.jsp 用 <c:forEach> </c:forEach> 遍历 所以先导入标签库,在进行商品遍历
<%@ page language="java" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> --要用EL表达式 先导入标签库 <HTML> <HEAD> <meta http-equiv="Content-Language" content="zh-cn"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="${pageContext.request.contextPath}/css/Style1.css" rel="stylesheet" type="text/css" /> <script language="javascript" src="${pageContext.request.contextPath}/js/public.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js"> <script type="text/javascript"> function addProduct() { window.location.href = "${pageContext.request.contextPath}/AddProductUIServlet"; } function del(pid){ var isdel=confirm("确认删除吗?"); if(isdel){ location.href = "${pageContext.request.contextPath}/DeleteProductServlet?pid="+pid; } } /* 写一个匿名函数 */ $(function(){ $("#is_hot option[value='${Condition.is_hot}']").prop("selected",true); $("#cid option[value='${Condition.cid}']").prop("selected",true); }) </script> </HEAD> <body> <br> <form id="Form1" name="Form1" action="${pageContext.request.contextPath}/ConditionServlet" method="post"> 商品名称:<input type="text" name="pname" value="${Condition.pname }"> 是否热门:<select name="is_hot" id="is_hot"> <option value="">请选择</option> <option value="1">是</option> <option value="0">否</option> </select> 所属分类:<select name="cid" id="cid"> <option value="">请选择</option> <c:forEach items="${CategoryList }" var="cate"> <option value="${cate.cid }">${cate.cname }</option> </c:forEach> </select> <input type="submit" value="搜索"> <table cellSpacing="1" cellPadding="0" width="100%" align="center" bgColor="#f5fafe" border="0"> <TBODY> <tr> <td class="ta_01" align="center" bgColor="#afd1f3"><strong>商品列表</strong> </TD> </tr> <tr> <td class="ta_01" align="right"> <button type="button" id="add" name="add" value="添加" class="button_add" onclick="addProduct()"> 添加</button> </td> </tr> <tr> <td class="ta_01" align="center" bgColor="#f5fafe"> <table cellspacing="0" cellpadding="1" rules="all" bordercolor="gray" border="1" id="DataGrid1" style="BORDER-RIGHT: gray 1px solid; BORDER-TOP: gray 1px solid; BORDER-LEFT: gray 1px solid; WIDTH: 100%; WORD-BREAK: break-all; BORDER-BOTTOM: gray 1px solid; BORDER-COLLAPSE: collapse; BACKGROUND-COLOR: #f5fafe; WORD-WRAP: break-word"> <tr style="FONT-WEIGHT: bold; FONT-SIZE: 12pt; HEIGHT: 25px; BACKGROUND-COLOR: #afd1f3"> <td align="center" width="18%">序号</td> <td align="center" width="17%">商品图片</td> <td align="center" width="17%">商品名称</td> <td align="center" width="17%">商品价格</td> <td align="center" width="17%">是否热门</td> <td width="7%" align="center">编辑</td> <td width="7%" align="center">删除</td> </tr> <c:forEach items="${ProductList }" var="pro" varStatus="vs"> <tr onmouseover="this.style.backgroundColor = 'white'" onmouseout="this.style.backgroundColor = '#F5FAFE';"> <td style="CURSOR: hand; HEIGHT: 22px" align="center" width="18%" >${vs.count }</td> <td style="CURSOR: hand; HEIGHT: 22px" align="center" width="17%"><img width="40" height="45" src="${pageContext.request.contextPath }/${pro.pimage}"></td> <td style="CURSOR: hand; HEIGHT: 22px" align="center" width="17%">${pro.pname }</td> <td style="CURSOR: hand; HEIGHT: 22px" align="center" width="17%">${pro.market_price }</td> <td style="CURSOR: hand; HEIGHT: 22px" align="center" width="17%">${pro.is_hot==1?"是":"否" }</td> <td align="center" style="HEIGHT: 22px"><a href="${ pageContext.request.contextPath }/EditProductServlet?pid=${pro.pid}"> <img src="${pageContext.request.contextPath}/images/i_edit.gif" border="0" style="CURSOR: hand"> </a></td> <td align="center" style="HEIGHT: 22px"><a href="javascript:void(0)" onClick="del('${pro.pid}')"> <img src="${pageContext.request.contextPath}/images/i_del.gif" width="16" height="16" border="0" style="CURSOR: hand"> </a></td> </tr> </c:forEach> </table> </td> </tr> </TBODY> </table> </form> </body> </HTML>