13-Javaweb-JSPmvc模式 JDBC事务 反射补充
目录
一、分层和事务
1-0 案例-使用mvc思想完成转账操作
1-1 mvc思想
1-2 MVC
1-3 jsp设计模式1 model1:(了解,已过时)
1-4 反射
1-4-1 获取class对象
1-4-2 可以获取对应类的构造方法(了解)
1-4-3 可以通过clazz创建一个对象(了解)
1-4-4 可以通过clazz获取所有的字段 getFiled()(了解中的了解)
1-4-5 可以通过clazz获取所有的方法
1-4-6 Method对象的invoke是有返回值,他的返回值就是目标方法执行的返回值
1-5 反射总结——class
1-6 javabean在model2中使用
1-7 分层:javaee的三层架构
1-7-1 web (jsp+servlet)
1-7-2 service 业务层
1-7-3 dao(data access object 数据访问对象——持久层)
1-8 事务
1-8-1 mysql中的事务
1-8-2 java中的事务
1-9 步骤分析
1-9-1 数据库和表
1-9-2 新建一个项目 day1301
1-9-3 导入jar包和工具类
1-9-4 新建一个account.jsp 表单
1-9-5 accountservlet
1-9-6 account方法中
1-9-7 dao中
1-9-8 在service添加事务
1-9-9 最终完善的工具类
1-9-10 将connection对象绑定当前线程重新实现转账
1-10 DButils
1-11 QueryRunner
1-11-1 使用DButils 重新实现转账
1-12 事务总结
1-12-1 事务的特性:★★★
1-12-2 不考虑隔离性会出现的读问题★★
1-12-3 通过设置数据库的隔离级别来避免上面的问题(理解)
1-12-4 了解 读问题的演示
1-12-5 四种隔离级别的效率
1-12-6 四种隔离级别的安全性
1-12-7 开发中绝对不允许脏读发生
1-12-8 java中控制隔离级别:(了解)
总结
一、分层和事务
1-0 案例-使用mvc思想完成转账操作
需求:
在一个页面上有汇款人 收款人 转账金额.一旦转账之后,汇款人金额减少,收款人金额增多.使用事务控制起来.
技术分析:
mvc思想
事务
1-1 mvc思想
servlet-->缺点:生成html内容太麻烦
|
jsp--->缺点:阅读起来不方便,维护比较困难
|
jsp+javabean:
jsp的model1:
jsp:接受请求,展示数据
javabean:和数据打交道
|
jsp+javabean+servlet
jsp的model2:
jsp:展示数据
javabean:和数据打交道
servlet:接受请求,处理业务逻辑
就是MVC思想的体现
1-2 MVC
就是将业务逻辑,代码,显示相分离的一种思想
M:model 模型 作用:主要是封装数据,封装对数据的访问 javabean
V:view 视图 作用:主要是用来展示数据 一般是jsp担任的
C:ctrl 控制 作用:接受请求,找到相应的javabean完成业务逻辑
1-3 jsp设计模式1 model1:(了解,已过时)
javabean+jsp
javabean在model1使用(了解) 两组动作标签 get | set Property<!-- 接受值 class:指定要封装成哪个对象 (反射) id="u" 为对象取名 --> <jsp:useBean id="u" class="com.itheima.domain.User"></jsp:useBean> <!-- setProperty:指定要为哪个属性设置什么值 name指定是谁 的属性 --> <jsp:setProperty property="name" name="u"/> <jsp:setProperty property="password" name="u"/><!-- 打印值--> <jsp:getProperty property="name" name="u"/>
1-4 反射
1-4-1 获取class对象
方式1:
Class clazz=Class.forName("全限定名")
方式2:
Class clazz=类名.class;
方式3:
Class clazz=对象.getClass;
1-4-2 可以获取对应类的构造方法(了解)
Constructor con = clazz.getConstructor(Class .. paramClass);
Person p = (Person) con.newInstance(参数);@Testpublic void f1() throws Exception{//1.获取class对象Class clazz=Class.forName("com.itheima.domain.Person");//2.获取构造器(了解)//Constructor con = clazz.getConstructor();//Person p = (Person) con.newInstance();//2.1获取带参的构造器(了解)Constructor con = clazz.getConstructor(String.class,String.class);Person p = (Person) con.newInstance("tom","123");//相当于 new Person("tom","123")System.out.println(p.getPassword());}
1-4-3 可以通过clazz创建一个对象(了解)
clazz.newInstance();//相当于调用的无参构造器
@Testpublic void f2() throws Exception{//1.获取class对象Class clazz=Class.forName("com.itheima.domain.Person");//2.获取构造器(了解)Person p = (Person) clazz.newInstance();}
1-4-4 可以通过clazz获取所有的字段 getFiled()(了解中的了解)
1-4-5 可以通过clazz获取所有的方法
Method m = clazz.getMethod("sleep");//获取公共的方法
Method m = clazz.getDeclaredMethod("sleep");//获取任意的方法
注意:若是私有的方法 必须让该方法可以访问
m.setAccessible(true);@Test//获取私有方法public void f3() throws Exception{//1.获取class对象Class clazz=Class.forName("com.itheima.domain.Person");Person p = (Person) clazz.newInstance();//2.获取方法//Method m = clazz.getMethod("sleep");//获取公共的方法Method m = clazz.getDeclaredMethod("sleep");//获取任意的方法//2.1若是私有的方法 必须让该方法可以访问m.setAccessible(true);//执行方法m.invoke(p);}
1-4-6 Method对象的invoke是有返回值,他的返回值就是目标方法执行的返回值
@Testpublic void f11() throws Exception{//1.获取class对象Class clazz=Class.forName("com.itheima.domain.Person");//2.获取私有的方法Method m = clazz.getDeclaredMethod("sleep", String.class);//让方法可以访问m.setAccessible(true);//3.让方法执行String res=(String) m.invoke(clazz.newInstance(),"侯振");System.out.println(res);}
1-5 反射总结——class
有了class对象之后,无所不能.
1-6 javabean在model2中使用
BeanUtils:可以看作封装数据一个工具类《10》
使用步骤:
1.导入jar包
2.使用BeanUtils.populate(Object bean,Map map);
1-7 分层:javaee的三层架构
1-7-1 web (jsp+servlet)
作用:
展示数据 ----jsp
-----servlet-------
接受请求
找到对应的service,调用方法 完成逻辑操作
信息生成或者页面跳转
1-7-2 service 业务层
作用:
完成业务操作
调用dao
1-7-3 dao(data access object 数据访问对象——持久层)
作用:
对数据库的curd操作
1-8 事务
就是一件完整的事情,包含多个操作单元,这些操作要么全部成功,要么全部失败.
例如:转账
包含转出操作和转入操作.
1-8-1 mysql中的事务
mysql中事务默认是自动提交,一条sql语句就是一个事务.
1 开启手动事务方式
方式1:关闭自动事务.(了解)
set autocommit = off(临时关闭)
方式2:手动开启一个事务.(理解)
start transaction;-- 开启一个事务
commit;-- 事务提交
rollback;-- 事务回滚——撤回
2 扩展:
oracle中事务默认是手动的,必须手动提交才可以.
3 例如:创建数据库和表
create database day13;
use day13;
create table account(
name varchar(20),
money int
);
insert into account values('aa','1000');
insert into account values('bb','1000');
4 完成 aa给bb转500;
update account set money = money - 500 where name='aa';
update account set money = money + 500 where name='bb';
1-8-2 java中的事务
Connection接口的api:★
setAutoCommit(false);//手动开启事务
commit():事务提交
rollback():事务回滚
扩展:了解 Savepoint还原点
void rollback(Savepoint savepoint) :还原到那个还原点
Savepoint setSavepoint() :设置还原点
1-9 步骤分析
1-9-1 数据库和表
1-9-2 新建一个项目 day1301
1-9-3 导入jar包和工具类
驱动 jdbcUtils
c3p0及其配置文件和工具类
dbutils
1-9-4 新建一个account.jsp 表单
<form method="post" action="${pageContext.request.contextPath }/account"><table><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><input type="submit" value="转账"></td><td></td></tr></table></form>
1-9-5 accountservlet
接受三个参数
调用accountservice.account方法完成转账操作
打印信息/*** 转账*/ public class AccountServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//0.设置编码request.setCharacterEncoding("utf-8");//提交的编码response.setContentType("text/html;charset=utf-8");//相应的编码PrintWriter w = response.getWriter();//1.接受三个参数String fromUser=request.getParameter("fromuser");String toUser=request.getParameter("touser");String money=request.getParameter("money");//2.调用accountservice.account(fromuser,touser,money)try {//使用的threadlocalnew AccountService().account(fromUser,toUser,money);} catch (Exception e) {e.printStackTrace();w.print("转账失败");return;}//3.打印信息w.print("转账成功");}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);} }
1-9-6 account方法中
使用jdbc不考虑事务
调用dao完成转出操作
调用dao完成转入操作public class AccountService {/*** 转账* @param fromUser 转出方* @param toUser 转入方* @param money 金额* @throws Exception */public void account(String fromUser, String toUser, String money) {AccountDao dao = new AccountDao();//1.转出dao.accountOutfromUser,money);//2.转入dao.accountIn(conn,toUser,money); } }
1-9-7 dao中
一旦出现异常,钱飞了.
/*** 转出钱* @param fromUser* @param money* @throws SQLException */public void accountOut_(String fromUser, String money) throws SQLException {Connection conn=null;PreparedStatement st=null;ResultSet rs=null;try {conn=JdbcUtils.getConnection();//编写sqlString sql="update account set money = money - ? where name =?";//创建语句执行者st=conn.prepareStatement(sql);//设置参数st.setString(1, money);st.setString(2, fromUser);//执行sqlint i = st.executeUpdate();//处理System.out.println("出:"+i);} catch (SQLException e) {e.printStackTrace();throw e;}finally {JdbcUtils.closeResource(conn, st, rs);}}/*** 转入* @param toUser* @param money* @throws SQLException */public void accountIn_(String toUser, String money) throws SQLException {Connection conn=null;PreparedStatement st=null;ResultSet rs=null;try {conn=JdbcUtils.getConnection();//编写sqlString sql="update account set money = money + ? where name =?";//创建语句执行者st=conn.prepareStatement(sql);//设置参数st.setString(1, money);st.setString(2, toUser);//执行sqlint i = st.executeUpdate();//处理System.out.println("入:"+i);} catch (SQLException e) {e.printStackTrace();throw e;}finally {JdbcUtils.closeResource(conn, st, rs);}}
1-9-8 在service添加事务
要想避免这事情,必须添加事务,在service添加事务.
为了保证所有的操作在一个事务中,必须保证使用的是同一个连接
在service层我们获取了连接,开启了事务.如何dao层使用此连接呢????
- 方法1: 向下传递参数.
注意连接应该在service释放
public class AccountService {/*** 转账* @param fromUser 转出方* @param toUser 转入方* @param money 金额* @throws Exception */public void account(String fromUser, String toUser, String money) throws Exception {AccountDao dao = new AccountDao();Connection conn=null;try {//所有事务都成功了才提交//0.开启事务conn = JdbcUtils.getConnection();conn.setAutoCommit(false);//1.转出dao.accountOut(conn,fromUser,money);int i=1/0;//2.转入dao.accountIn(conn,toUser,money);//3.事务提交conn.commit();//连接释放JdbcUtils.closeConn(conn);} catch (Exception e) {e.printStackTrace();//事务回滚conn.rollback();//连接释放JdbcUtils.closeConn(conn);throw e;}} }
dao不需要创建和关闭conn
/*** 转出钱* @param fromUser* @param money* @throws SQLException */public void accountOut(Connection conn,String fromUser, String money) throws SQLException {PreparedStatement st=null;ResultSet rs=null;try {//编写sqlString sql="update account set money = money - ? where name =?";//创建语句执行者st=conn.prepareStatement(sql);//设置参数st.setString(1, money);st.setString(2, fromUser);//执行sqlint i = st.executeUpdate();//处理System.out.println("出:"+i);} catch (SQLException e) {e.printStackTrace();throw e;}finally {//JdbcUtils.closeResource(conn, st, rs);JdbcUtils.closeStatement(st);}}/*** 转入* @param toUser* @param money* @throws SQLException */public void accountIn(Connection conn,String toUser, String money) throws SQLException {PreparedStatement st=null;ResultSet rs=null;try {//编写sqlString sql="update account set money = money + ? where name =?";//创建语句执行者st=conn.prepareStatement(sql);//设置参数st.setString(1, money);st.setString(2, toUser);//执行sqlint i = st.executeUpdate();//处理System.out.println("入:"+i);} catch (SQLException e) {e.printStackTrace();throw e;}finally {//JdbcUtils.closeResource(conn, st, rs);JdbcUtils.closeStatement(st);}}
- 方法2:将connection对象绑定当前线程上 ThreadLocal类
jdk中有一个ThreadLocal类,
ThreadLocal 实例通常是类中的 private static 字段
它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
- ThreadLocal的方法:
构造:
new ThreadLocal()
set(Object value):将内容和当前线程绑定
Object get():获取和当前线程绑定的内容
remove():将当前线程和内容解绑
- 内部维护了map集合
map.put(当前线程,内容);
map.get(当前线程)
map.remove(当前线程)
- 修改 datesource 工具类
添加字段,修改 获取 和 释放 方法
public class DataSourceUtils {private static ComboPooledDataSource ds=new ComboPooledDataSource();private static ThreadLocal<Connection> tl=new ThreadLocal<>();/*** 获取数据源* @return 连接池*/public static DataSource getDataSource(){return ds;}/*** 从当前线程上获取连接* @return 连接* @throws SQLException*/public static Connection getConnection() throws SQLException{Connection conn = tl.get();//第一次获取没绑定,为空if(conn==null){//第一次获取 创建一个连接 和当前的线程绑定conn=ds.getConnection();//绑定tl.set(conn);}return conn;}/*** 释放连接* @param conn连接*/public static void closeConn(Connection conn) {if (conn != null) {try {conn.close();//和当前的线程解绑tl.remove();} catch (SQLException e) {e.printStackTrace();}conn = null;}}
添加事务操作
/*** 开启事务* @throws SQLException*/public static void startTransaction() throws SQLException{//获取连接//开启事务getConnection().setAutoCommit(false);;}/*** 事务提交*/public static void commitAndClose(){try {//获取连接Connection conn = getConnection();//提交事务conn.commit();//释放资源conn.close();//解除绑定tl.remove();} catch (SQLException e) {e.printStackTrace();}}/*** 事务回滚*/public static void rollbackAndClose(){try {//获取连接Connection conn = getConnection();//事务回滚conn.rollback();//释放资源conn.close();//解除绑定tl.remove();} catch (SQLException e) {e.printStackTrace();}}
1-9-9 最终完善的工具类
public class DataSourceUtils {private static ComboPooledDataSource ds=new ComboPooledDataSource();private static ThreadLocal<Connection> tl=new ThreadLocal<>();/*** 获取数据源* @return 连接池*/public static DataSource getDataSource(){return ds;}/*** 从当前线程上获取连接* @return 连接* @throws SQLException*/public static Connection getConnection() throws SQLException{Connection conn = tl.get();//第一次获取没绑定,为空if(conn==null){//第一次获取 创建一个连接 和当前的线程绑定conn=ds.getConnection();//绑定tl.set(conn);}return conn;}/*** 释放资源 * @param conn 连接* @param st 语句执行者* @param rs 结果集*/public static void closeResource(Connection conn, Statement st, ResultSet rs) {closeResource(st, rs);closeConn(conn);}/*** 释放资源 * @param st 语句执行者* @param rs 结果集*/public static void closeResource(Statement st, ResultSet rs) {closeResultSet(rs);closeStatement(st);}/*** 释放连接* @param conn连接*/public static void closeConn(Connection conn) {if (conn != null) {try {conn.close();//和当前的线程解绑tl.remove();} catch (SQLException e) {e.printStackTrace();}conn = null;}}/*** 释放语句执行者 * @param st 语句执行者*/public static void closeStatement(Statement st) {if (st != null) {try {st.close();} catch (SQLException e) {e.printStackTrace();}st = null;}}/*** 释放结果集* @param rs 结果集*/public static void closeResultSet(ResultSet rs) {if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}rs = null;}}/*** 开启事务* @throws SQLException*/public static void startTransaction() throws SQLException{//获取连接//开启事务getConnection().setAutoCommit(false);;}/*** 事务提交*/public static void commitAndClose(){try {//获取连接Connection conn = getConnection();//提交事务conn.commit();//释放资源conn.close();//解除绑定tl.remove();} catch (SQLException e) {e.printStackTrace();}}/*** 事务回滚*/public static void rollbackAndClose(){try {//获取连接Connection conn = getConnection();//事务回滚conn.rollback();//释放资源conn.close();//解除绑定tl.remove();} catch (SQLException e) {e.printStackTrace();}} }
1-9-10 将connection对象绑定当前线程重新实现转账
servlet
//2.调用accountservice.account(fromuser,touser,money)try {//使用的threadlocalnew AccountService4tl().account(fromUser,toUser,money);//new AccountService4DB().account(fromUser, toUser, money);} catch (Exception e) {e.printStackTrace();w.print("转账失败");return;}
service
public class AccountService4tl {/*** 转账* @param fromUser 转出方* @param toUser 转入方* @param money 金额* @throws Exception */public void account(String fromUser, String toUser, String money) throws Exception {AccountDao4tl dao = new AccountDao4tl();try {//0.开启事务DataSourceUtils.startTransaction();//1.转出dao.accountOut(fromUser,money);int i=1/0;//2.转入dao.accountIn(toUser,money);//3.事务提交DataSourceUtils.commitAndClose();} catch (Exception e) {e.printStackTrace();DataSourceUtils.rollbackAndClose();throw e;}} }
dao
public class AccountDao4tl {/*** 转出钱* @param fromUser* @param money* @throws SQLException */public void accountOut(String fromUser, String money) throws SQLException {PreparedStatement st=null;ResultSet rs=null;Connection conn=null;try {conn=DataSourceUtils.getConnection();//编写sqlString sql="update account set money = money - ? where name =?";//创建语句执行者st=conn.prepareStatement(sql);//设置参数st.setString(1, money);st.setString(2, fromUser);//执行sqlint i = st.executeUpdate();//处理System.out.println("出:"+i);} catch (SQLException e) {e.printStackTrace();throw e;}finally {DataSourceUtils.closeResource(st, rs);}}/*** 转入* @param toUser* @param money* @throws SQLException */public void accountIn(String toUser, String money) throws SQLException {PreparedStatement st=null;ResultSet rs=null;Connection conn=null;try {conn=DataSourceUtils.getConnection();//编写sqlString sql="update account set money = money + ? where name =?";//创建语句执行者st=conn.prepareStatement(sql);//设置参数st.setString(1, money);st.setString(2, toUser);//执行sqlint i = st.executeUpdate();//处理System.out.println("入:"+i);} catch (SQLException e) {e.printStackTrace();throw e;}finally {DataSourceUtils.closeResource(st, rs);}} }
1-10 DButils
1.创建queryrunner
2.编写sql
3.执行sql
1-11 QueryRunner
构造:
new QueryRunner(DataSource ds):自动事务
new QueryRunner():手动事务
常用方法:(传入线程中的conn)
update(Connection conn,String sql,Object ... params):执行的cud操作
query(Connection conn....):执行查询操作
注意:
一旦使用手动事务,调用方法的时候都需要手动传入connection,并且需要手动关闭连接
1-11-1 使用DButils 重新实现转账
servlet
//2.调用accountservice.account(fromuser,touser,money)try {//使用的threadlocal//new AccountService4tl().account(fromUser,toUser,money);new AccountService4DB().account(fromUser, toUser, money);} catch (Exception e) {e.printStackTrace();w.print("转账失败");return;}
service
public class AccountService4DB {/*** 转账* @param fromUser 转出方* @param toUser 转入方* @param money 金额* @throws Exception */public void account(String fromUser, String toUser, String money) throws Exception {AccountDao4DB dao = new AccountDao4DB();try {//0.开启事务DataSourceUtils.startTransaction();//1.转出dao.accountOut(fromUser,money);int i=1/0;//2.转入dao.accountIn(toUser,money);//3.事务提交DataSourceUtils.commitAndClose();} catch (Exception e) {e.printStackTrace();DataSourceUtils.rollbackAndClose();throw e;}} }
dao
public class AccountDao4DB {public void accountOut(String fromUser, String money) throws SQLException {//创建queryrunnerQueryRunner qr = new QueryRunner();//编写sqlString sql="update account set money =money - ? where name =?";//执行sqlqr.update(DataSourceUtils.getConnection(), sql, money,fromUser);//DbUtils.rollbackAndClose 在向下传递中支持,(不常用)}public void accountIn(String toUser, String money) throws SQLException {QueryRunner qr=new QueryRunner();String sql="update account set money =money + ? where name =?";qr.update(DataSourceUtils.getConnection(), sql, money,toUser);} }
1-12 事务总结
1-12-1 事务的特性:★★★
ACID
原子性:事务里面的操作单元不可切割,要么全部成功,要么全部失败
一致性:事务执行前后,业务状态和其他业务状态保持一致.(转账前后银行总金额保持不变)
隔离性:一个事务执行的时候最好不要受到其他事务的影响
持久性:一旦事务提交或者回滚.这个状态都要持久化到数据库中
1-12-2 不考虑隔离性会出现的读问题★★
脏读:在一个事务中读取到另一个事务没有提交的数据
不可重复读:在一个事务中,两次查询的结果不一致(针对的update操作) 转账,一方没有提交,查询结果为 之前的
虚读(幻读):在一个事务中,两次查询的结果不一致(针对的insert操作)
1-12-3 通过设置数据库的隔离级别来避免上面的问题(理解)
read uncommitted 读未提交 上面的三个问题都会出现
read committed 读已提交 可以避免脏读的发生
repeatable read 可重复读 可以避免脏读和不可重复读的发生
serializable 串行化 可以避免所有的问题
1-12-4 了解 读问题的演示
演示脏读的发生:
将数据库的隔离级别设置成 读未提交
set session transaction isolation level read uncommitted;
查看数据库的隔离级别
select @@tx_isolation;手动开启事务 start transaction; 转钱 不提交
避免脏读的发生,将隔离级别设置成 读已提交
set session transaction isolation level read committed;
不可避免不可重复读的发生.
避免不可重复读的发生 经隔离级别设置成 可重复读
set session transaction isolation level repeatable read;
演示串行化 可以避免所有的问题
set session transaction isolation level serializable;
锁表的操作.
1-12-5 四种隔离级别的效率
read uncommitted>read committed>repeatable read>serializable
1-12-6 四种隔离级别的安全性
read uncommitted<read committed<repeatable read<serializable
1-12-7 开发中绝对不允许脏读发生
mysql中默认级别:repeatable read
oracle中默认级别:read committed
1-12-8 java中控制隔离级别:(了解)
Connection的api
void setTransactionIsolation(int level)
level是常量
总结
- 1 jsp的设计模式
model1:jsp+javabean(了解)
model2:jsp+servlet+javabean
jsp:展示数据
servlet:接受请求,处理业务逻辑
javabean:封装数据,封装对数据的访问
- 2 MVC
将业务逻辑 代码 显示相分离
M:model 模型 封装数据,封装对数据的访问
V:view 视图 展示数据,目前jsp担任
C:ctrl 控制 接受请求
- 3 三层架构
web:
作用:
展示数据
接受请求
调用service
页面跳转,信息的生成
service
作用:
处理业务逻辑
调用dao
dao
作用:
对数据库的curd操作
- 4 反射
1.获取class对象
2.通过class获取构造器
3.通过class获取字段
4.通过class获取指定的方法
5.可以执行方法
- 5 事务
就是一件完整的事情,可以包含多个操作单元,这些单元要么全部成功,要么全部失败
- 6 mysql中的事务(了解)
默认自动提交.
控制事务:
1.关闭自动事务
2.手动打开一个事务
start transaction;
commit;
rollback;
- 7 java中事务:(★)
Connection的api
setAutoCommit(false):手动开启事务
commit():事务提交
rollback():事务回滚
- 8 如何使用同一个connection
1.向下传递
2.将连接绑定到当前线程
ThreadLocal
set(Object value)
Object get()
remove()
- 9 DBUtils中事务控制
QueryRunner:
构造:
new QueryRunner(Datasource ds)://自动事务.调用方法的不需要传入connection,资源不用我们释放.
new QueryRunner()://手动事务.调用方法的必须传入connection,需要手动提交事务或者回滚事务.必须手动的释放资源
- 10 事务的特性 ★★★
ACID
原子性 一致性 隔离性 持久性
- 11 不考虑隔离性会出现的读问题★★
脏读 不可重复度 虚读
- 12 数据库的隔离级别
read uncommitted 读未提交 不能避免任何问题
★read committed 读已提交 避免脏读
★repeatable read 可重复度 避免脏读和不可重复读的发生
serializable 串行化 避免所有的问题
13-Javaweb-JSPmvc模式 JDBC事务 反射补充相关推荐
- jdbc事务 jta事务_将非事务性资源绑定到JTA事务中的几种模式
jdbc事务 jta事务 我最近发表了一篇有关如何将非事务性资源(如Web服务/微服务)绑定到全局分布式事务中的文章,以便自动处理恢复. 多年来,我经常不得不将"非事务性"系统集成 ...
- JavaWeb:用JDBC操作数据库
JDBC系列阅读 JavaWeb:用JDBC操作数据库 JavaWeb:JDBC之事务 JavaWeb:JDBC之数据库连接池 使用JDBC实现水果超市管理系统 1. 什么是JDBC JDBC的全称是 ...
- JavaWeb开发模式:C/S模式,B/S模式,JSP+JavaBean模式,JSP+Servlet+JavaBean模式
JavaWeb开发模式 1.C/S开发模式 1.C/S架构:客户端Client/服务端Server: a.出现较早,主要应用于局域网内: b.胖客户端:需要特定软件支持(安装客户端) 逻辑关系图如下: ...
- 事务处理总结【JDBC事务|JTA事务|容器事务
http://space.itpub.net/13956325/viewspace-598381 一.什么是Java事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACI ...
- JDBC事务和JTA事务的区别 --包含spring事务 声明式事务
2019独角兽企业重金招聘Python工程师标准>>> 一.事务概述 事务表示一个由一系列的数据库操作组成的不可分割的逻辑单位,其中的操作要么全做要么全都不做. 与事务相关的操作主要 ...
- Java事务处理总结【JDBC事务|JTA事务|容器事务】
来源:http://hi.baidu.com/wangking/blog/item/4d28730945364aaa2eddd4a9.html 一.什么是 Java事务 通常的观念认为,事务仅与数据库 ...
- JDBC事务--软件开发三层架构--ThreadLocal
JDBC事务--软件开发三层架构--ThreadLocal 一.JDBC事务 1.概述: 事务是指逻辑上的一组操作!这一组操作,通常认为是一个整体,不可拆分! 特点:同生共死;事务内的这一组操作要么全 ...
- Java的JDBC事务详解
事务的特性:1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行.2) 一致性(consistency):事务在完成时 ...
- Java+Oracle实现事务——JDBC事务
J2EE支持JDBC事务.JTA事务和容器事务事务,这里说一下怎样实现JDBC事务. JDBC事务是由Connection对象所控制的,它提供了两种事务模式:自己主动提交和手动提交,默认是自己主动提交 ...
最新文章
- 近距离接触RAC DRM
- 配置C++和C#开发ICE环境
- 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers
- MySQL的权限分配
- GetClientRect相当于GetWindowRect和ScreenToClient区别
- 贝壳如何docker安装openwrt_OpenWrt 中 使用 Docker 安装可道云出错。
- CentOS7安装Nginx,全网最快安装教程
- python数据存储系列教程——python对象与json字符串的相互转化,json文件的存储与读取
- Spring源码之BeanDefinitionRegistryPostProcessor内部执行流程
- 基于安卓Android银行排队叫号系统设计与实现
- UG NX 12 草图技巧与方法分析
- 计算机粉碎文件后电脑桌面没有画面,我电脑桌面上自己新建的一个文件夹,用完后删除不掉,用360强力粉碎也不管用,删掉一开机就出来了,求解决...
- Clonezilla 再生龙
- ecs共享型s6怎么样?
- “四舍六入五成双规则” 与 C语言如何实现“四舍五入”
- 漫画丨什么是边缘云?
- Legolas工业自动化平台案例 —— 水源地自动化监控系统
- LeetCode(172) Factorial Trailing Zeroes
- 【转载】Pyramid的权限管理
- Vue文件上传、下载
热门文章
- 30+场技术论坛 1000+科技新品发布 今年云栖大会我们关注什么?
- TDD测试驱动开发的基础是什么?
- 杠杆交易如何预防被割韭菜?
- 扎心啊,老铁!支付宝支付,同步通知session失效问题
- 常州85后女刑警陈露:10年练就火眼让蛛丝马迹“开口”
- Nespresso 借助 Orange Business Services 的访客 Wi-Fi 服务提升其全球精品店的用户体验...
- PXE + kickstart批量装机及问题解决方案
- python reload is not defined_name 'reload' is not defined解决方法
- 电商客户消费预测模型-基于数千万真实在线零售数据__企业调研_论文科研_毕业设计
- lora模块oled液晶屏显示动画