1.为什么@Transactional注解的事务没有回滚?
伪代码:
public class testTransactional {
@Transactional
public void methodA(String id) {
g4Dao.update(id);
methodB(id);
}
public void methodB(String id){
Boolean result = g4Dao.insert(id);
if (!result) {
throw new Exception("我要抛异常");
}
}
}
正常来说,methodA被@Transactional标注,那么里面的操作应该在一个事务中进行。
但是,如果methodB操作失败,抛出异常,methoA的update操作没有回滚,这是什么原因呢?
@Transactional注解默认情况下只有遇到Uncheck Exception才会回滚,对于Check Exception不会进行任何操作。
解决方案:
1.可以抛出Uncheck Exception。
throw new RuntimeException("我要抛异常");
2.在注解@Transactional配置回滚异常
@Transactional(rollbackFor = Exception.class)
java异常体系
2.为什么SimpleDateFormate有时候日期格式化不是期望值
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR,2019);
//月份从0开始
calendar.set(Calendar.MONTH,11);
calendar.set(Calendar.DAY_OF_MONTH,29);
System.out.println("Date: 2019.12.29转换String" + sdf.format(calendar.getTime()));
期望输出2019-12-29,但是输出结果却是:
原因:
SimpleDateFormate在表示年份的时候存在两种格式,一种是大写的YYYY,一种是小写的yyyy。这两种格式表达的含义是不一样的。YYYY
表示的是"周年",也就是这一周所在的年份。yyyy
表示的这一天所在的年份。
3.Random产生的随机数不随机?
获取一个0到25随机数的功能:
public static Integer randomNumber() {
Random random = new Random(1000);
return random.nextInt(26);
}
执行可以发现,每次获取的随机数都一样。
原因:
每次获取随机数,都会创建一个新的Random对象。Random是基于Seed值产生一个伪随机序列。由于新的Random对象的Seed都一样,随机的算法一样,导致生成的随机数一样。
可以将随机对象Random定义为类对象。避免这个问题。如:
static Random random = new Random();
public static Integer randomNumber() {
return random.nextInt(26);
}
4.三元表达式,抛出空指针异常
public Integer compareAndSum(Integer number1,Integet number2,Integer defaultNumber) {
return number1 > number2 ? number1 + number2:defaultNumber;
}
如果number1 小于 number2的时候,就会抛出空指针异常。
原因:
number1 + number2,会被转换为基础类型。所以对defaultNumber进行转换的时候,机会抛出空指针异常。
如果使用三元表达式,我们要确认会不会存在参数为null的情况。如果存在,就需要用if…else…代替。
5.为什么ThreadLocal对象会取到预期之外的值?
我们知道在Java Web中,每一次用户请求都会从容器的线程池取一个新的线程来负责执行请求。在这个线程中,我们经常使用ThreadLocal来存储上下文信息,这样,就可以在线程的整个声明周期里都可以取用这个应用上下文信息。
但是,在使用ThreadLocal对象的时候,会遇到明明没有设置值却可以从中取到数据的现象。
原因:
因为线程我们是从线程池中取出来的,两次请求完全有可能是使用的同一个线程。如果第一个请求使用完后,没有清除ThreadLocal,那么这个线程的ThreadLocal对象还是会存在上下文信息。
所以,我们要记住每次使用线程后,把ThreadLocal对象清除掉就可以了。