Java进阶-12.事务

一、javaweb的设计模式

1.jsp模式介绍

SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式(model1模式),一种是Servlet+JSP+JavaBean模式(model2模式)。

1)Model1模式介绍

model1模式各部分功能分析

JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这种模式下,JavaBean用于封装业务数据,JSP即负责处理用户请求,又显示数据。


model1模式的优缺点

优点:简单快捷,对开发人员要求不高。

缺点:所有的操作都在jsp页面中,其中访问数据库的API是在jsp页面中完成的,难以维护,不适合做比较复杂应用 ,它只适合中小型项目。

2)Model2模式介绍

model2模式各部分功能分析

Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。 Servlet+JSP、JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。

model2模式的优缺点

优点:维护方便,开发人员各司其职,互不干涉,有利于开发中的分工,有利于组件的重用。比较适合做比较复杂应用,它适合做中大型项目。

缺点:项目开发难度增大,对开发人员的要求也随之提高。

2.javaBean介绍

JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性。众所周知,属性名称符合这种模式,其他Java 类可以通过自身机制发现和操作这些JavaBean 的属性。

JavaBean可分为两种:一种是有用户界面(UI,User Interface)的JavaBean;还有一种是没有用户界面,主要负责处理事务(如数据运算,操纵数据库)的JavaBean。JSP通常访问的是后一种JavaBean。而我们在javaweb开发中使用JavaBean主要是用于进行数据的运算(数据的封装)。

1)javaBean在model1模式下的使用

jsp:useBean

jsp:setProperty

jsp:getProperty

例如:

username:<input type="text" name="username"><br>

password:<input type="password" name="password"><br>

jsp中使用bean标签来封装数据

<jspuseBean id="u" class="com.itheima.domain.User"></jspuseBean><!--相当于  User u=new User()-->

<jspsetProperty property="name" name="u"/><!--相当于  u.setName(...)-->

<jspsetProperty property="password" name="u"/>

当某个网页将数据传输到该jsp界面时,上面的代码就可以自动封装这些数据,并通过下面的代码进行获取属性值。

<jspgetProperty property="name" name="u"/>

要求:页面上组件的名称必须与javaBean的bean属性名称一致。bean属性是get/set 后面的名称。

2)javaBean在model2模式下的使用(BeanUtils工具使用)

在model1模式下我们使用jsp提供的标签来将数据封装到javaBean中,那么我们在model2模式下,因为jsp已经不在进行功能的处理,只是用于显示数据,这时怎样将数据封装到JavaBean中?如果我们通过手动封装是可以的,但是如果参数过多,那么代码量很大,这时我们可以通过反射机制来完成请求参数的封装。

1.得到所有请求参数 request.getParameterMap();

2.得到javaBean类的Class对象,得到这个类中所有方法 getDeclaredMethods();

3.判断methods中是否具有setXxx方法,从map集合的key中获取;

4.如果查找到这个方法,通过这个方法的invoke进行调用method.invoke()方法;

1.获取class对象
    方式1:Class clazz=Class.forName("全限定名")
    方式2:Class clazz=类名.class;
    方式3:Class clazz=对象.getClass;
2.可以获取对应类的构造方法(了解)
    Constructor con = clazz.getConstructor(Class .. paramClass);
    Person p = (Person) con.newInstance(参数);
    例如:
    Constructor con = clazz.getConstructor(String.class,String.class);
    Person p = (Person) con.newInstance("tom","123");
3.可以通过clazz创建一个对象(了解)
    clazz.newInstance();//相当于调用的无参构造器
4.可以通过clazz获取所有的字段 getFiled()(了解中的了解)
5.可以通过clazz获取所有的方法
    Method m = clazz.getMethod("sleep");//获取公共的方法
    Method m = clazz.getDeclaredMethod("sleep");//获取任意的方法
    注意:若是私有的方法 必须让该方法可以访问
        m.setAccessible(true);
6.Method对象的invoke方法是有返回值,他的返回值就是目标方法执行的返回值

上述代码我们自己完成会很复杂,在开发中,我们可以使用BeanUtils工具来完成它的底层实现就是通过java中的内省机制(最底层就是反射)来完成的。

3)BeanUtils工具介绍

Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。BeanUtils工具的使用步骤:

1.导入jar包:commons-logging-1.1.1.jar、commons-beanutils-1.8.3.jar     

2.使用:BeanUtils.populate(javaBean对象, request.getParameterMap());

4)BeanUtils工具类型转换

在使用BeanUtils工具对数据进行封装时,它是如何做到将请求参数(字符串)封装到javaBean的不同类型的属性上的呢?

BeanUtils默认类型转换介绍:在BeanUtils工具中,有默认的类型转换,我们可以在org.apache.commons.beanutils.converters包下查看到它们提供的默认的类型转换器。

BeanUtils自定义类型转换器:在开发中,有很多情况下,数据类型的转换使用BeanUtils工具可能不完全够用,这时我们就可以通过自定义类型转换器来完成操作。步骤如下:

1.创建一个类,实现这个接口org.apache.commons.beanutils.Converter,该接口是BeanUtils中所有类型转换器的根接口。

2.重写方法public Object convert(Class type, Object value)

       在这个方法中完成类型转换,这个方法的返回值就是赋值给javaBean中对应的属性

       type:要转换成的类型

       value:表单传递过来的属性值

3.注册类型转换器

       ConvertUtils.register(javaBean对象,要转换成的类型.class);

二、MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。MVC模式最早被Trygve Reenskaug提出,成为施乐帕罗奥多研究中心(Xerox PARC)的Smalltalk语言发明的一种软件设计模式。MVC可对程序的后期维护和扩展提供了方便,并且使程序某些部分的重用提供了方便。而且MVC也使程序简化,更加直观。

Mmodel模型:主要是封装数据,封装对数据的访问

Vview视图:主要是用来展示数据一般是jsp担任的

Cctrl控制:接受请求找到相应的javabean完成业务逻辑

1.javaweb三层架构介绍

所谓的三层架构是由web层,业务层及数据层组成的,它们分别完成各自的工作,如下所示:

Web层:包含jsp和Servlet等与web相关的内容;

业务层:也称Service层,业务层中不包含JavaWeb的API,它只关心业务逻辑;

数据层:有时候也称为是持久层,其功能主要是负责数据库的访问,简单的说法就是实现对数据表的Select,Insert,Update,Delete的操作。

其中,web层是与web相关的内容,包括jsp和servlet,以及request、response、session、ServletContext等,这些对象只能出现在web层,不能出现在业务层;同样,业务层只关心业务逻辑,例如登录,注册功能,其中注册就是向数据库中插入一条数据,这样在数据层就对应一个方法,因此业务层依赖于数据层,可以这样理解:业务层的一个功能是由数据层的若干个对数据库的操作组成的。而web层将用户输入的数据传递给业务层,业务层处理之后将结果返回给web层,由web层再展示给用户。也就是说web层依赖于业务层。由于业务层和数据层没有出现javaweb的API,因此业务层和数据层是可重用的,甚至可以应用在非web环境中。

2.javaweb三层架构与MVC的区别分析

三层架构是一个分层式的软件体系架构设计,它可适用于任何一个项目。MVC是一个设计模式,它是根据项目的具体需求来决定是否适用于该项目。

那么架构跟设计模式有什么区别呢?

我们从接手一个项目开始,首先,我们需要进行架构设计,一般我们采用的就是分层式的架构设计,即我们的三层架构。然后,在确定了架构以后,我们再根据项目的具体需求去考虑是否需要应用一些设计模式,比如是否应用我们的MVC模式,抽象工厂模式等等。

三、事务

事务,一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元。这些单元要么全都成功,要么全都不成功。

1.mysql中的事务

mysql中事务默认是自动提交一条sql语句就是一个事务。

        show variables like '%autocommit%'

开启手动事务方式

方式1:关闭自动事务(了解)

            set autocommit = off;

方式2:手动开启一个事务.(理解)

            start transaction;-- 开启一个事务

            commit;-- 事务提交

            rollback;-- 事务回滚

扩展:oracle中事务默认是手动的必须手动提交才可以。

2.java中的事务

Connection接口的api

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

        commit():事务提交

        rollback():事务回滚

扩展:了解 Savepoint还原点

        void rollback(Savepoint savepoint) :还原到那个还原点

        Savepoint setSavepoint() :设置还原点

为了保证所有的操作在一个事务中,必须保证使用的是同一个连接。service层我们获取了连接,开启了事务如何dao层使用此连接?

方法1:向下传递参数注意连接应该在service释放

方法2:可以将connection对象绑定当前线程上,jdk中有一个ThreadLocal类,ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。

ThreadLocal的方法:

构造:new ThreadLocal()

    set(Object value):将内容和当前线程绑定

    Object get():获取和当前线程绑定的内容

    remove():将当前线程和内容解绑

内部维护了map集合

    map.put(当前线程,内容);

    map.get(当前线程)

    map.remove(当前线程)

3.事务的特性

简称ACID(Atomicity Consistency Isolation Durability),分别是:

原子性:原子性对应的英文是Atomicity,即表示事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败;

一致性:一致性对应的英文是Consistency,事务执行后,数据库状态与其它业务规则保持一致。例如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的;

隔离性:隔离性对应的英文是Isolation,是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰;

持久性:持久性对应的英文是Durability,指的是一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

不同的事务,其一致性的表现形式是不同的,事务的其他三大特性其实都是为了事务的一致性服务的。

不考虑隔离性会出现的读问题

    脏读:在一个事务中读取到另一个事务没有提交的数据

    不可重复读:在一个事务中,两次查询的结果不一致(针对的update操作)

    虚读(幻读):在一个事务中,两次查询的结果不一致(针对的insert操作)

通过设置数据库的隔离级别来避免上面的问题(理解)

    read uncommitted    读未提交    上面的三个问题都会出现

    read committed        读已提交  可以避免脏读的发生

    repeatable read    可重复读 可以避免脏读和不可重复读的发生

    serializable          串行化     可以避免所有的问题

演示脏读的发生:

将数据库的隔离级别设置成读未提交

            set session transaction isolation level read uncommitted;

查看数据库的隔离级别

            select @@tx_isolation;

避免脏读的发生,将隔离级别设置成读已提交

            set session transaction isolation level read committed;

不可避免不可重复读的发生。

避免不可重复读的发生隔离级别设置成可重复读

set session transaction isolation level  repeatable read;

演示串行化可以避免所有的问题

set session transaction isolation level  serializable;

四种隔离级别的效率

read uncommitted>read committed>repeatable read>serializable

四种隔离级别的安全性

read uncommitted<read committed<repeatable read<serializable

开发中绝对不允许脏读发生

        mysql中默认级别:repeatable read

        oracle中默认级别:read committed

mysql中设置

数据库默认有事务的隔离级别,mysql 中查看与修改事务的隔离级别

set session transaction isolation level 隔离级别;设置事务隔离级别

select @@tx_isolation; 查询当前事务隔离级别

jdbc中设置事务隔离级别

在java.sql.Connection接口中提供:setTransactionIsolation(int level) ;

参数可以取 Connection 常量之一:

Connection.TRANSACTION_READ_UNCOMMITTED、

Connection.TRANSACTION_READ_COMMITTED、

Connection.TRANSACTION_REPEATABLE_READ

Connection.TRANSACTION_SERIALIZABLE。                             

(注意,不能使用 Connection.TRANSACTION_NONE,因为它指定了不受支持的事务。)

DBUtils中事务控制

QueryRunner:
    构造:
        new QueryRunner(Datasource ds)//自动事务,调用方法的不需要传入connection,资源不用我们释放。
        new QueryRunner()//手动事务,调用方法的必须传入connection,需要手动提交事务或者回滚事务。必须手动的释放资源。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值