当前位置:首页 > 天道酬勤 > 正文内容

面试还有什么问题要问(团干面试)

张世龙2021年12月21日 04:14天道酬勤1210

一、JDBC

之前的SUN公司想要创建一个可以连接全球所有数据库的API,但从一开始就发现这是不可能的工作,因为每个供应商的数据库服务器差异太大。 随后,SUN与数据库供应商展开了讨论。 结果,提供了一系列的SUN访问数据库的规范,即一系列的接口,提供了连接到数据库的协议标准,以及各数据库供应商根据SUN的规范访问其数据库服务器的一系列app SUN提供的规范称为JDBC,允许访问符合各制造商提供的JDBC规范的专有数据库的API称为驱动程序。

数据库连接池:

C3P0

dbcp--应用程序公共池

Druid

二、ORM

国际标准

Hibernate是一个开源对象关系映射框架,它非常轻量级地封装了JDBC。 这是一个映射POJO和数据库表、完全自动化的orm框架,Hibernate自动生成和自动执行SQL语句,以便Java程序员使用面向对象的思维操作数据库。

Hibernate需要定义实体类和hbm映射关系文件(IDE通常提供工具生成)。

在Hibernate中,可以用HQL、Criteria和本机SQL三种方法处理数据库。 也可以将其实现为JPA适配器,然后使用JPA接口进行操作。

我的贝斯

MyBatis是一个优秀的持久层框架,支持定制的SQL、存储过程和高级映射。 MyBatis可以避免几乎所有的JDBC代码,手动设置参数并获取结果集。 Mybatis可以使用简单的XML或注释来配置和映射本机信息,并将接口和Java的POJOS(plainoldJavaobjects )映射到数据库中的记录

Mybatis和Hibernate有什么区别?

Hibernate是全自动的,Mybatis是半自动的。

我的贝斯

优点:为原生SQL(XML语法),直观,容易优化缺点)繁琐,可以用Mybatis-generator、Mybatis-Plus等插件弥补Hibernate

优点:在简单的场景中不写SQL(hql、Cretiria、SQL )的缺点:难以优化SQL、对DBA不友好的Spring管理事务

首先,让我们看看JDBC是如何操作事务的。

publicvoidupdatePrice () throwsSQLException{

特里

连接连接=获取连接(;

//关闭自动提交

conn.set自动提交(假);

string SQL='更新代码设置=? whereid=?' ;

preparedstatementptmt=conn.preparestatement (SQL;

组合双精度(13500 );

PMT.setstring(2,'1' );

//执行

ptmt.execute (;

//提交事务

conn.commit (;

缓存(执行) {

//回滚事务

conn.rollback (;

电子打印机

ackTrace();         }     }

再看看Spring是如何无侵入地进行事务管理的?

实现原理:事务管理器+AOP

源码分析Spring事务实现过程

示例代码: 我在goodsService.updatePrice方法上加了事务注解。

 @RequestMapping("/updateprice")     public String updateprice(Double price,Integer age){         goodsService.updatePrice(1,price);         int i=10/0;         userService.updateAge(1,age);         return "sucess";     } 请求进入controller,调用goodsService的时候,调用的实际上是goodsService的代理对象

到代理类的方法中org.springframework.aop.framework.ReflectiveMethodInvocation#proceed进入事务拦截器的方法

里面有个TransactionInterceptor TransactionInterceptor方法里面进行了事务管理protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,    final InvocationCallback invocation) throws Throwable {   // If the transaction attribute is null, the method is non-transactional.   TransactionAttributeSource tas = getTransactionAttributeSource();   final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);   final PlatformTransactionManager tm = determineTransactionManager(txAttr);   final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);   if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {    // Standard transaction demarcation with getTransaction and commit/rollback calls.    TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);    Object retVal = null;    try {     // This is an around advice: Invoke the next interceptor in the chain.     // This will normally result in a target object being invoked.     //执行目标方法     retVal = invocation.proceedWithInvocation();    }    catch (Throwable ex) {     //回滚     exception     completeTransactionAfterThrowing(txInfo, ex);     throw ex;    }    finally {     cleanupTransactionInfo(txInfo);    }    //提交事务    commitTransactionAfterReturning(txInfo);    return retVal;   }   ...

上述是简单场景的事务处理,如果是多个service方法,并且都加了@Transactional注解,那事务怎么算呢?那就需要学习Spring里的事务传播了。

public Class ServiceA{     @Transactional     void methodA(){         //....         } } public Class ServiceB{     @Transactional     void methodB(){         //....         } }

七种事务的传播行为:

PROPAGATION_REQUIRED (默认) 表示当前方法必须在一个具有事务的上下文中运行,如有客户端有事务在进行,那么被调用端将在该事务中运行,否则的话重新开启一个事务。PROPAGATION_SUPPORTS 表示当前方法不必须在一个具有事务的上下文中运行,如:ServiceA.methodA()调用ServiceB.methodB(),如果methodA方法上有事务,那么methodB加入他的事务,如果methodA上没有事务,那么methodB也不开事务PROPAGATION_MANDATORY 必须被开启事务的方法调用,否则报错PROPAGATION_REQUIRES_NEW 强制自己开启一个新的事务,如果一个事务已经存在,那么将这个事务挂起.如ServiceA.methodA()调用ServiceB.methodB(),methodB()上的传播级别是PROPAGATION_REQUIRES_NEW的话,那么如果methodA报错,不影响methodB的事务,如果methodB报错,那么methodA是可以选择是回滚或者提交的,就看你是否将methodB报的错误抛出还是try catch了.PROPAGATION_NOT_SUPPORTED 总是非事务的执行,并且挂起任何事务.就是如果methodA方法执行到methodB这里了,methodA的事务就被挂起,然后methodB非事务的执行,然后等methodB方法运行结束,methodA的事务再继续.这个的好处就是methodB报错了不会让methodA回滚.PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常PROPAGATION_NESTED 表示如果当前方法正有一个事务在运行中,则该方法应该运行在一个嵌套事务中 ,被嵌套的事务可以独立于被封装的事务中进行提交或者回滚。如果封装事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务。如果封装事务不存在,则同propagation. required的一样

事务失效的几个原因:

spring的事务注解@Transactional只能放在public修饰的方法上才起作用,如果放在其他非public(private,protected)方法上,虽然不报错,但是事务不起作用如果采用spring+springmvc,则context:component-scan重复扫描问题可能会引起事务失败。如果spring和mvc的配置文件中都扫描了service层,那么事务就会失效。 原因:因为按照spring配置文件的加载顺序来讲,先加载springmvc配置文件,再加载spring配置文件,我们的事物一般都在srping配置文件中进行配置,如果此时在加载srpingMVC配置文件的时候,把servlce也给注册了,但是此时事物还没加载,也就导致后面的事物无法成功注入到service中。所以把对service的扫描放在spring配置文件中或是其他配置文件中。如使用mysql且引擎是MyISAM,则事务会不起作用,原因是MyISAM不支持事务,可以改成InnoDB引擎@Transactional注解开启配置,必须放到listener里加载,如果放到DispatcherServlet的配置里,事务也是不起作用的。Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional注解,只能xjyb设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。在业务代码中如果抛出RuntimeException异常,事务回滚;但是抛出Exception,事务不回滚;默认对RuntimeException回滚如果在加有事务的方法内,使用了try...catch..语句块对异常进行了捕获,而catch语句块没有throw new RuntimeExecption异常,事务也不会回滚在类A里面有方法a 和方法b, 然后方法b上面用 @Transactional加了方法级别的事务,在方法a里面 调用了方法b,方法b里面的事务不会生效。原因是在同一个类之中,方法互相调用,切面无效,而不仅仅是事务。这里事务之所以无效,是因为spring的事务是通过aop实现的。

代码示例:

可以看出这个this,并不是代理对象,事务也就不能生效了。

扫描二维码推送至手机访问。

版权声明:本文由花开半夏のブログ发布,如需转载请注明出处。

本文链接:https://www.zhangshilong.cn/work/26077.html

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。