jpa多线程事务

文章介绍了一种在JPA中处理多线程事务回滚的方法,通过共享EntityManager和EntityTransaction,在主线程中控制事务的提交和回滚。在测试代码中,创建线程池执行多个线程操作,确保所有子线程执行完毕后才提交事务,如果子线程中发生异常则进行回滚。
摘要由CSDN通过智能技术生成

百度都百度不到jpa多线程的事务回滚,废话少说,就是干,

实现思路(可看可不看,本人也不喜欢罗里吧嗦的,想直接看干货就跳过这里,直接执行代码):

jpa本身是不支持多线程事务,所以要手动实现事务的提交和回滚,网上可参考的太复杂,而且没用的太多,自己干吧,

首先,排除一般的影响事务回滚的条件(jpa事务失效的 场景),事务回滚的前提就是同一个连接,统一提交事务,
但是多线程,是多个实例,都不是同一个连接,自然不能统一回滚了,

实现思路:想要实现统一的管理,就要共享同一个事务,同一个connection,我们只能手动管理主线程和子线程,所以要共享EntityManager和EntityTransaction,
需要注意的是不能直接在方法外来初始化EntityManager和EntityTransaction,会报错,通过请求,再获取对象,赋值就可以了
通过内部类,来共享这两个对象,就实现了两个测试的内部类,Thread1和Thread2,
然后通过线程池,来执行多个线程,需要注意的就是,要确定子线程都执行完毕了,再提交事务,不然的话,子线程还在执行,主线程就提交了事务,多线程事务就没法生效
代码都经过测试,直接复制粘贴,代入自己数据源测试就知道了

代码实例

	/**
	 * 注入EntityManager实例
	 */
	@Autowired
	private EntityManagerFactory entityManagerFactory;

	//作为多线程的事务共享,从而统一提交或回滚,不能在这里直接createEntityManager和getTransaction
	EntityManager entityManager;
	EntityTransaction transaction;

	//测试方法
	@ResponseBody
	@RequestMapping(value = "/test")
	public RetMsgBean testThread() throws Exception {

		//请求的时候给实例和事务赋值
		entityManager = entityManagerFactory.createEntityManager();
		transaction = entityManager.getTransaction();

		try {

			//开始事务
			transaction.begin();

			//执行插入数据操作
			Query query = entityManager.createNativeQuery("insert into pt_business_logs(id) value (?)");
			//传入参数
			query.setParameter(1,"11111");
			//提交数据库
			query.executeUpdate();
			//创建线程池
			ExecutorService service= Executors.newFixedThreadPool(10);
			//执行事务
			service.execute(new Thread1());
			//执行事务
			service.execute(new Thread2());

			//结束线程池
			service.shutdown();
			/**
			 * 线程没有结束,就等待500毫秒,可以随意调整等待时间,反正就是要等子线程执行完,
			 * 不等子线程的话,子线程还在执行,主线程有可能就直接进行commit操作了,多线程事务回滚就无法生效了
			 */
			while (!service.isTerminated()) {
				Thread.sleep(500);
				System.out.println("等待子线程执行");
			}

			//事务执行完成的提示
			System.out.println("提交事务");

			//提交事务
			transaction.commit();
		} catch (Exception e) {
			//发生异常进行回滚,主线程的回滚不能控制子线程,只是针对主线程的异常
			if (transaction != null) {
				transaction.rollback();
			}
			e.printStackTrace();
			System.out.println("发生异常");
		}finally {
			entityManager.close();
		}

		//RetMsgBean无所谓,这是一个自定义的返回值类
		return RetMsgBean.init();
	}

	//内部类,线程1,通过继承Runnable实现
class Thread1 implements Runnable{

	@Override
	public void run() {
		try {
			//执行数据库操作
			Query query = entityManager.createNativeQuery("insert into pt_business_logs(id) value (?)");
			query.setParameter(1,"222222");
			query.executeUpdate();
			//故意抛出异常
			System.out.println(1/0);
		} catch (Exception e) {
			e.printStackTrace();
			//进行回滚
			transaction.rollback();
		}
	}
}
	//内部类,线程2,通过继承Runnable实现
class Thread2 implements Runnable{

	@Override
	public void run() {
		try {
			Query query = entityManager.createNativeQuery("insert into pt_business_logs(id) value (?)");
			query.setParameter(1,"333333");
			query.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			transaction.rollback();
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值