求助:jfinal2.2事务不回滚

CC88 发布于 2016/08/09 17:43
阅读 540
收藏 3

@JFinal 詹总,最近项目中使用了jfinal2.2,始终无法使用事务回滚操作,查找了很久,一直未能找到原因。通过运行jfinal_demo已经证实不是mysql的问题,表是innoDB。mysql版本是5.7.12。请帮忙看看是什么原因,感激!

一、jfinalConfig配置文件如下

package com.platform.config;

import javax.servlet.ServletContext;

import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.core.JFinal;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.dialect.AnsiSqlDialect;
import com.jfinal.plugin.activerecord.tx.TxByMethods;
import com.jfinal.plugin.c3p0.C3p0Plugin;
import com.jfinal.plugin.redis.RedisPlugin;
import com.jfinal.render.FreeMarkerRender;
import com.jfinal.render.ViewType;
import com.platform.contorller.AdminController;
import com.platform.contorller.DemoController;
import com.platform.contorller.HomeController;
import com.platform.contorller.InitDataController;
import com.platform.contorller.UploadController;
import com.platform.contorller.route.BaseRoute;
import com.platform.contorller.route.DailyRoute;
import com.platform.contorller.route.EvadeRoute;
import com.platform.handler.UrlHandler;
import com.platform.interceptor.AuthInteceptor;
import com.platform.job.QuartzPlugin;
import com.platform.model.Admin;
import com.platform.model.BlackList;
import com.platform.model.BusinessCall;
import com.platform.model.CgCar;
import com.platform.model.ChangeShift;
import com.platform.model.ChargeCheck;
import com.platform.model.ChargeSituation;
import com.platform.model.CheckSummary;
//import com.platform.model.CheckSummary;
import com.platform.model.DictDistance;
import com.platform.model.DictEntry;
import com.platform.model.DictRoad;
import com.platform.model.DictType;
import com.platform.model.EscapeFeeHandle;
import com.platform.model.FbCar;
import com.platform.model.FreeCar;
import com.platform.model.GrayList;
import com.platform.model.GrayStatistics;
import com.platform.model.IcCard;
import com.platform.model.ImportantCheckFee;
import com.platform.model.JkMonitor;
import com.platform.model.Lane;
import com.platform.model.LeavePost;
import com.platform.model.Lose;
import com.platform.model.ModelRules;
import com.platform.model.ModelType;
import com.platform.model.ModelVersion;
import com.platform.model.MonitorroomTransition;
import com.platform.model.NoCard;
import com.platform.model.Organization;
import com.platform.model.OverTime;
import com.platform.model.PreCard;
import com.platform.model.Resource;
import com.platform.model.ResourceAuth;
import com.platform.model.Role;
import com.platform.model.RoleAdmin;
import com.platform.model.RoleResource;
import com.platform.model.SelfExamAndCorrt;
import com.platform.model.ServiceCheck;
import com.platform.model.ShiftArrangement;
import com.platform.model.SpecialCar;
import com.platform.model.SpecialCase;
import com.platform.model.Station;
import com.platform.model.SuperwidthCar;
import com.platform.model.SysConfig;
import com.platform.model.TzCar;
import com.platform.model.UnusualTransd;
import com.platform.model.Utype;
import com.platform.model.WorkDuty;
import com.platform.model.base.UploadFilePic;
import com.platform.model.data.DataEntryStation;
import com.platform.model.data.DataExitStation;
import com.platform.model.data.DataSpot;
import com.platform.model.data.EtcEntryMediData;
import com.platform.model.data.EtcExitMediData;
import com.platform.model.data.MtcEntryMediData;
import com.platform.model.data.MtcExitMediData;
import com.platform.model.data.SpotMediData;
import com.platform.model.init.InitDataFlowfee;
import com.platform.model.monitor.FlowFeeStatistics;
import com.platform.model.monitor.MonitorFlowFee;
import com.platform.model.query.DictStation;
import com.platform.model.query.EarlyWarning;
import com.platform.model.query.FeeCheckEntryStation;
import com.platform.model.query.FeeCheckExitStation;
import com.platform.model.query.FeeCheckVehicleInfo;
import com.platform.model.query.QueryEvidence;
import com.platform.model.query.QueryEvidenceEntryStation;
import com.platform.model.query.QueryEvidenceExitStation;
import com.platform.model.query.QueryVehicleInfo;
import com.platform.service.DataStatisticsService;
import com.platform.service.EvadeDataService;
import com.platform.service.db.DbService;
import com.platform.service.mq.Receiver;
import com.platform.service.mq.Sender;
import com.platform.test.Blog;
import com.platform.test.BlogController;
import com.platform.test.IndexController;
/**
 * API引导式配置
 */
public class FeeConfig extends JFinalConfig {
	//此变量控制是生产服务器还是测试服务器
	public static boolean DEBUG = true;
	/**
	 * 配置常量
	 */
	public void configConstant(Constants me) {
		// 加载少量必要配置,随后可用PropKit.get(...)获取值
		if(DEBUG)
			PropKit.use("com/platform/config/config_dev.properties");
		else
			PropKit.use("com/platform/config/config_produce.properties");
		
		me.setDevMode(PropKit.getBoolean("devMode", false));
		me.setViewType(ViewType.FREE_MARKER);
		me.setError404View("/common/error.html");
		me.setError500View("/common/error.html");
	}
	
	/**
	 * 配置路由
	 */
	public void configRoute(Routes me) {
		me.add("/", HomeController.class);
		me.add("/admin", AdminController.class);	// 第三个参数省略时默认与第一个参数值相同,在此即为 "/admin"
		me.add("/upload", UploadController.class);
		me.add("/example", DemoController.class);
		me.add("/initData", InitDataController.class);
		me.add(new BaseRoute());
		me.add(new EvadeRoute());
		me.add(new DailyRoute());
		
		me.add("/test", IndexController.class);	// 第三个参数为该Controller的视图存放路径
		me.add("/blog", BlogController.class);	// 第三个参数省略时默认与第一个参数值相同,在此即为 "/blog"
	}

	/**
	 * 配置插件
	 */
	public void configPlugin(Plugins me) {
		// 配置MTC中间库
        C3p0Plugin c3p0Plugin_mtcMediData = new C3p0Plugin(PropKit.get("mtcMediData_url"), PropKit.get("mtcMediData_username"), PropKit.get("mtcMediData_password"),PropKit.get("mtcMediData_driverClassName"));
        c3p0Plugin_mtcMediData.setInitialPoolSize(10);
        c3p0Plugin_mtcMediData.setMaxIdleTime(1800);
        c3p0Plugin_mtcMediData.setMaxPoolSize(100);
        c3p0Plugin_mtcMediData.setMinPoolSize(10);
        c3p0Plugin_mtcMediData.setAcquireIncrement(3);
        me.add(c3p0Plugin_mtcMediData);
        ActiveRecordPlugin arp_mtcMediData = new ActiveRecordPlugin("dbMtc",c3p0Plugin_mtcMediData);
        arp_mtcMediData.setDialect(new AnsiSqlDialect());
        arp_mtcMediData.setTransactionLevel(4);
        arp_mtcMediData.setShowSql(false);
        arp_mtcMediData.addMapping("data_mtc_entry", "ID",MtcEntryMediData.class);
        arp_mtcMediData.addMapping("data_mtc_exit", "ID",MtcExitMediData.class);
        me.add(arp_mtcMediData);
        
        // 配置ETC中间库
        C3p0Plugin c3p0Plugin_etcMediData = new C3p0Plugin(PropKit.get("etcMediData_url"), PropKit.get("etcMediData_username"), PropKit.get("etcMediData_password"),PropKit.get("etcMediData_driverClassName"));
        c3p0Plugin_etcMediData.setInitialPoolSize(10);
        c3p0Plugin_etcMediData.setMaxIdleTime(1800);
        c3p0Plugin_etcMediData.setMaxPoolSize(100);
        c3p0Plugin_etcMediData.setMinPoolSize(10);
        c3p0Plugin_etcMediData.setAcquireIncrement(3);
        me.add(c3p0Plugin_etcMediData);
        ActiveRecordPlugin arp_etcMediData = new ActiveRecordPlugin("dbEtc",c3p0Plugin_etcMediData);
        arp_etcMediData.setDialect(new AnsiSqlDialect());
        arp_etcMediData.setTransactionLevel(4);
        arp_etcMediData.setShowSql(false);
        arp_etcMediData.addMapping("data_etc_entry", "ListNo",EtcEntryMediData.class);
        arp_etcMediData.addMapping("data_etc_exit", "ListNo",EtcExitMediData.class);
        me.add(arp_etcMediData);
        
        // 配置识别点中间库
        C3p0Plugin c3p0Plugin_spotMediData = new C3p0Plugin(PropKit.get("spotMediData_url"), PropKit.get("spotMediData_username"), PropKit.get("spotMediData_password"),PropKit.get("spotMediData_driverClassName"));
        c3p0Plugin_spotMediData.setInitialPoolSize(10);
        c3p0Plugin_spotMediData.setMaxIdleTime(1800);
        c3p0Plugin_spotMediData.setMaxPoolSize(100);
        c3p0Plugin_spotMediData.setMinPoolSize(10);
        c3p0Plugin_spotMediData.setAcquireIncrement(3);
        me.add(c3p0Plugin_spotMediData);
        ActiveRecordPlugin arp_spotMediData = new ActiveRecordPlugin("dbSpot",c3p0Plugin_spotMediData);
        arp_spotMediData.setDialect(new AnsiSqlDialect());
        arp_spotMediData.setTransactionLevel(4);
        arp_spotMediData.setShowSql(false);
        arp_spotMediData.addMapping("VichleInfo", "id",SpotMediData.class);
        me.add(arp_spotMediData);
		
		// 配置分析数据存储数据库
		C3p0Plugin c3p0Plugin_data = new C3p0Plugin(PropKit.get("databaseUrl_data"),PropKit.get("username_data"), PropKit.get("password_data"));
		c3p0Plugin_data.setInitialPoolSize(10);
		c3p0Plugin_data.setMaxIdleTime(1800);
		c3p0Plugin_data.setMaxPoolSize(100);
		c3p0Plugin_data.setMinPoolSize(10);
		c3p0Plugin_data.setAcquireIncrement(3);
		me.add(c3p0Plugin_data);
		// 配置ActiveRecord插件
		ActiveRecordPlugin arp_data = new ActiveRecordPlugin("dbData",c3p0Plugin_data);
		arp_data.setTransactionLevel(4);
		arp_data.setShowSql(false);
		arp_data.addMapping("T_EVADE_MODEL_TYPE", "ID",ModelType.class);
		arp_data.addMapping("T_EVADE_MODEL_VERSION","ID", ModelVersion.class);
		arp_data.addMapping("T_EVADE_MODEL_RULE","ID", ModelRules.class);
		arp_data.addMapping("SYS_CONFIG","ID", SysConfig.class);
		arp_data.addMapping("DATA_ENTRYSTATION","ID", DataEntryStation.class);
		arp_data.addMapping("DATA_EXITSTATION","ID", DataExitStation.class);
		arp_data.addMapping("VICHLEINFO","BIZID", DataSpot.class);
		arp_data.addMapping("init_data_flowfee", "id",InitDataFlowfee.class);
		me.add(arp_data);
		
		// 配置查询统计数据库
		C3p0Plugin c3p0Plugin_query = new C3p0Plugin(PropKit.get("databaseUrl_query"),PropKit.get("username_query"), PropKit.get("password_query"));
		c3p0Plugin_query.setInitialPoolSize(10);
		c3p0Plugin_query.setMaxIdleTime(1800);
		c3p0Plugin_query.setMaxPoolSize(100);
		c3p0Plugin_query.setMinPoolSize(10);
		c3p0Plugin_query.setAcquireIncrement(3);
		me.add(c3p0Plugin_query);
		ActiveRecordPlugin arp_query = new ActiveRecordPlugin("dbQuery",c3p0Plugin_query);
		arp_query.setTransactionLevel(4);
		arp_query.setShowSql(false);
		arp_query.addMapping("DP_USER","USERID",Admin.class);
		arp_query.addMapping("DP_ROLE","ROLEID",Role.class);
		arp_query.addMapping("DP_USERROLE","USERID,ROLEID",RoleAdmin.class);
	    arp_query.addMapping("DP_ROLERESOURCE","ROLEID,RESOURCECODE",RoleResource.class);
	    arp_query.addMapping("DP_RESOURCE_AUTH","RESOURCECODE,DICTID,ROLEID",ResourceAuth.class);
		arp_query.addMapping("T_EVADE_GRAYLIST", "ID", GrayList.class);
		arp_query.addMapping("DP_RESOURCE", "RESOURCECODE", Resource.class);
		arp_query.addMapping("DP_ORGANIZATION", "ORGID", Organization.class);
		arp_query.addMapping("T_MONITOR_FLOWFEE", "id", MonitorFlowFee.class);
		arp_query.addMapping("T_MONITOR_FLOWFEE_YEARMONTH", "id", FlowFeeStatistics.class);
		arp_query.addMapping("T_EVADE_EVIDENCE", "ID", QueryEvidence.class);
		arp_query.addMapping("T_EVADE_TJ", "id", GrayStatistics.class);
		arp_query.addMapping("EVADE_EVIDENCE_ENTRYSTATION", "ID", QueryEvidenceEntryStation.class);
		arp_query.addMapping("EVADE_EVIDENCE_EXITSTATION", "ID", QueryEvidenceExitStation.class);
		arp_query.addMapping("T_EVADE_VICHLEINFO", "ID", QueryVehicleInfo.class);
		arp_query.addMapping("T_DICT_DISTANCE", "ID", DictDistance.class);
		arp_query.addMapping("T_EVADE_BLACKLIST", "ID", BlackList.class);
		arp_query.addMapping("T_DICT_ROAD", "ID", DictRoad.class);
		arp_query.addMapping("T_DICT_STATION", "ID", DictStation.class);
		arp_query.addMapping("T_UPLOADFILE", "FILE_ID", UploadFilePic.class);
		
		arp_query.addMapping("T_DAILY_UNUSUALTRANS","ID",UnusualTransd.class);//异常交易
		arp_query.addMapping("T_DAILY_NOCARD","ID",NoCard.class);//无卡车
		arp_query.addMapping("T_DAILY_UTYPE","ID",Utype.class);//U型车
		arp_query.addMapping("T_DAILY_CG","ID",CgCar.class);//冲关车
		arp_query.addMapping("T_DAILY_FREE","ID",FreeCar.class);//免费车
		arp_query.addMapping("T_DAILY_SPECIALCAR","ID",SpecialCar.class);//绿通车
		arp_query.addMapping("T_DICT_STATION","STATIONID",Station.class);//站点
		arp_query.addMapping("DP_DICT_TYPE","DICTTYPEID",DictType.class);//数据字典
		arp_query.addMapping("DP_DICT_ENTRY","DICTID",DictEntry.class);//数据字典
		arp_query.addMapping("T_DAILY_OVERTIME","ID",OverTime.class);//超时车
		arp_query.addMapping("T_DAILY_TZ","ID",TzCar.class);//跳站车
		arp_query.addMapping("T_DAILY_FB","ID",FbCar.class);//复磅车
		arp_query.addMapping("T_DICT_LANE","ID",Lane.class);//车道管理
		
		arp_query.addMapping("T_DAILY_JK_SUM","ID",JkMonitor.class);//解款监禁
		arp_query.addMapping("T_DAILY_LOSE","ID",Lose.class);//丢失卡
		arp_query.addMapping("T_DAILY_PRECARD","ID",PreCard.class);//预制卡登记
		
		arp_query.addMapping("T_DAILY_SERVICE_CHECK", "ID", ServiceCheck.class);//文明优质服务督查
		arp_query.addMapping("T_DAILY_CHARGE_CHECK", "ID", ChargeCheck.class);//收费稽查情况登记
		arp_query.addMapping("T_MONTHLY_SELFEXAMANDCORRT", "ID" ,SelfExamAndCorrt.class);//自查自纠月度汇总
		arp_query.addMapping("T_DAILY_SPECIALCASE", "ID", SpecialCase.class);//特殊情况记录
		arp_query.addMapping("T_MONTHLY_CHECKSUMMARY", "ID", CheckSummary.class);//稽查情况月度汇总
		arp_query.addMapping("T_DAILY_BUSINESSCALL", "ID", BusinessCall.class);//业务电话
		arp_query.addMapping("T_DAILY_SUPERWIDTHCAR", "ID", SuperwidthCar.class);//超宽车使用情况
		arp_query.addMapping("T_DAILY_CHARGESITUATION", "ID", ChargeSituation.class);//收费情况
		arp_query.addMapping("T_DAILY_MONITORROOMTRANSITION", "ID", MonitorroomTransition.class);//监控室交接记录
		arp_query.addMapping("T_DAILY_LEAVEPOST", "ID",  LeavePost.class);//离岗顶岗
		arp_query.addMapping("T_DAILY_CHANGESHIFT", "ID", ChangeShift.class);//换班
		arp_query.addMapping("T_DAILY_SHIFTARRANGEMENT", "ID", ShiftArrangement.class);//排班
		arp_query.addMapping("T_DAILY_WORKDUTY", "ID", WorkDuty.class);//当班信息
		arp_query.addMapping("T_DAILY_ICCARD", "ID", IcCard.class);//IC卡流量及卡盒
		
		arp_query.addMapping("T_IMPORTANT_FEECHECK", "ID", ImportantCheckFee.class);//重点收费稽查
		arp_query.addMapping("T_EVADE_ESCAPEFEE", "ID", EscapeFeeHandle.class);//逃费车辆处理
		arp_query.addMapping("T_FEECHECK_ENTRYSTATION", "ID", FeeCheckEntryStation.class);//逃费车辆处理入口信息
		arp_query.addMapping("T_FEECHECK_EXITSTATION", "ID", FeeCheckExitStation.class);//逃费车辆处理出口信息
		arp_query.addMapping("T_FEECHECK_VICHLEINFO", "id", FeeCheckVehicleInfo.class);//逃费车辆处理识别点信息
		arp_query.addMapping("T_FEECHECK_EARLYWARNNING", "ID", EarlyWarning.class);//收费稽查预警信息
		
		arp_query.addMapping("blog", "id", Blog.class);
		
		me.add(arp_query);

		// 配置redis服务
		RedisPlugin rp = null;
		if(StrKit.notBlank(PropKit.get("redis_pwd"))){
			rp = new RedisPlugin("data", PropKit.get("redis_url"),PropKit.getInt("redis_port"), PropKit.get("redis_pwd"));
		}else{
			rp = new RedisPlugin("data", PropKit.get("redis_url"),PropKit.getInt("redis_port"));
		}
				
		//最大空闲连接数
		rp.getJedisPoolConfig().setMaxIdle(60);
		//最大连接数
		rp.getJedisPoolConfig().setMaxTotal(100);
		//获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
		rp.getJedisPoolConfig().setMaxWaitMillis(-1);
		//逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
		rp.getJedisPoolConfig().setMinEvictableIdleTimeMillis(1800000);
		//最小空闲连接数, 默认0
		rp.getJedisPoolConfig().setMinIdle(0);
		//每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
		rp.getJedisPoolConfig().setNumTestsPerEvictionRun(3);
		me.add(rp);
		
		if(PropKit.get("appType").equals("statistics")|| PropKit.get("appType").equals("all")){
			//配置数据清理、转换、分析调度服务
			me.add(new QuartzPlugin());
		}
	}
	
	/**
	 * 配置全局拦截器
	 */
	public void configInterceptor(Interceptors me) {
		me.add(new AuthInteceptor());
	}
	
	/**
	 * 配置处理器
	 */
	public void configHandler(Handlers me) {
		me.add(new UrlHandler());
	}
	
	/**
	 * 在系统启动后调用的方法
	 */
    public void afterJFinalStart() {

    	//每次启动,初始化数据并加载动态数据源
    	DbService.bandingDataSource();
    	DataStatisticsService.getInstance().DataClear(false);

    	try {
    		//设置cas单点路径
			FreeMarkerRender.getConfiguration().setSharedVariable("casLoginUrl", PropKit.get("casLoginUrl"));
			ServletContext servletContext = JFinal.me().getServletContext();
			String contextPath = servletContext.getContextPath();
			FreeMarkerRender.getConfiguration().setSharedVariable("ctx", contextPath);
			FreeMarkerRender.getConfiguration().setSharedVariable("filectx", PropKit.get("nginx_url"));
			
			if(PropKit.get("appType").equals("data") || PropKit.get("appType").equals("all")){
				//启动消息队列消费端
				for(int i=0;i<PropKit.getInt("activemq_receiver_num");i++){
					new Thread(new Receiver("data_processing")).start();
					new Thread(new Receiver("data_getting_etc")).start();
					new Thread(new Receiver("data_getting_mtc")).start();
					new Thread(new Receiver("data_getting_spot")).start();
					System.out.println("开启第"+(i+1)+"个data队列消费端");
				}
				for(int i=0;i<PropKit.getInt("activemq_queues_num");i++){
					Sender.SenderMessage("data_getting_etc", "");
					Sender.SenderMessage("data_getting_mtc", "");
					Sender.SenderMessage("data_getting_spot", "");
					System.out.println("开始第"+(i+1)+"个data数据队列");
				}
			}
			if(PropKit.get("appType").equals("server") || PropKit.get("appType").equals("all")){
				//启动消息队列消费端
				for(int i=0;i<PropKit.getInt("activemq_receiver_num");i++){
					//分析入口流水表
				    new Thread(new Receiver("analysis_entry")).start();
					//分析出口流水表
					new Thread(new Receiver("analysis_exit")).start();
					 //分析识别点信息表
	                new Thread(new Receiver("analysis_spot")).start();
	                //分析灰名单
	                new Thread(new Receiver("analysis_gray")).start();
	                //分析重点稽查
	                new Thread(new Receiver("analysis_importantcheck")).start();
	                //分析收费稽查预警
	                new Thread(new Receiver("analysis_earlywarning")).start();
	                //更新收费稽查预警
	                new Thread(new Receiver("update_earlywarning")).start();
					System.out.println("开启第"+(i+1)+"个server队列消费端");
				}
				for(int i=0;i<PropKit.getInt("activemq_queues_num");i++){
					Sender.SenderMessage("analysis_entry", "");
		            Sender.SenderMessage("analysis_exit", "");
	                Sender.SenderMessage("analysis_spot", "");
	                Sender.SenderMessage("analysis_gray", "");
	                Sender.SenderMessage("analysis_importantcheck", "");
	                Sender.SenderMessage("analysis_earlywarning", "");
	                Sender.SenderMessage("update_earlywarning", "");
	            	System.out.println("开始第"+(i+1)+"个server数据队列");
				}
			}
			
			if(PropKit.get("appType").equals("statistics") || PropKit.get("appType").equals("all")){
				//启动消息队列消费端
				for(int i=0;i<PropKit.getInt("activemq_receiver_num");i++){
					 //流量及收费统计:将redis数据统计到数据库中
	                new Thread(new Receiver("statistics_flowfee")).start();
					System.out.println("开启第"+(i+1)+"个statistics队列消费端");
				}
				for(int i=0;i<PropKit.getInt("activemq_queues_num");i++){
					 Sender.SenderMessage("statistics_flowfee", "");
					 System.out.println("开始第"+(i+1)+"个statistics数据队列");
				}
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    

	/**
	 * 建议使用 JFinal 手册推荐的方式启动项目
	 * 运行此 main 方法可以启动项目,此main方法可以放置在任意的Class类定义中,不一定要放于此
	 */
	public static void main(String[] args) {
		JFinal.start("WebRoot", 80, "/", 5);
	}
}



二、对应的事务测试controller文件

package com.platform.contorller;

import java.util.List;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.ext.render.excel.PoiRender;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;

public class DemoController extends Controller {
	

	
	
	/**
	 * 事务回滚 
	 */
	@Before(Tx.class)
	public void rollback(){
//		UploadService us = Duang.duang(UploadService.class);
//		us.uploadtest1();
//		us.uploadtest2();
		System.out.println("事务开始");
		Db.use("dbQuery").update("update t_uploadfile set FILE_CLASS = ? where FILE_ID = ?",
				"img1", "656");
		
		Db.use("dbQuery").update("update t_uploadfile set FILE_CLASS = ? where FILE_ID = ?",
				null, "657");
		System.out.println("事务结束");
	}
}



三、工程引用的Jar包包括

四、测试过程说明:

1、对t_uploadfile 表进行update操作时,FILE_CLASS是不能为空的,第一次更新正常,第二次更新异常,数据应该回滚。但是多次尝试都未能回滚数据

2、用jfinal_demo测试工程连接该数据库及使用t_uploadfile 表进行测试,可以正常回滚,说明mysql数据库没有问题。

3、将jfinal_demo里的示例文件,除demoConifg.java文件外其他的blog示例文件都拷贝到我新建的工程中,blog示例不能回滚。


加载中
0
护士的小黄瓜
护士的小黄瓜
多数据源事务,用哪个框架能解决?
0
JFinal
JFinal

    @Before(Tx.class) 是默认是针对主数据源做事务,而你在代码中使用了 Db.use("dbQuery") 切换到了其它数据库,所以不能成功,解决办法是在 @Before 后面再添加一个 @TxConfig("dbQuery") 即可。

    这里要再说明一点,jfinal 不支持跨数据源的事务,这个属于分布式事务的范畴。只支持针对于一个数据源中的事务,楼主的代码事务都处于 dbQuery 这一个数据源中,是支持的。

JFinal
JFinal
回复 @CC88 : 直接使用 J2EE 中的 JTA 就可以,只不过集成到 jfinal 中没有极简方案,代码比较丑露,所以 jfinal 也一直暂缓引入,直到有极简方案。通常建议将业务划分一下,将需要跨数据源的事务,分解为不需要跨数据库的独立数据库。或者将需要跨库的操作的数据放在同一个库之中
CC88
CC88
对于跨数据源的事务支持,在jfinal中请问有没有好的解决方案
返回顶部
顶部