运行环境:JBoss Data Grid 6.3.0
Carmart(Transactional)与Carmart基本一样,但是多了事务,不同于数据库事务,这里是内存级的事务。
Carmart(Transactional)只能运行在library mode下,因为目前只有library mode支持事务。
学习重点:
1. 事务是如何配置开启的?
@ApplicationScoped
public class JBossASCacheContainerProvider implements CacheContainerProvider {
private Logger log = Logger.getLogger(this.getClass().getName());
private BasicCacheContainer manager;
public BasicCacheContainer getCacheContainer() {
if (manager == null) {
GlobalConfiguration glob = new GlobalConfigurationBuilder()
.nonClusteredDefault() //Helper method that gets you a default constructed GlobalConfiguration, preconfigured for use in LOCAL mode
.globalJmxStatistics().enable() //This method allows enables the jmx statistics of the global configuration.
.jmxDomain("org.infinispan.carmart.tx") //prevent collision with non-transactional carmart
.build(); //Builds the GlobalConfiguration object
Configuration loc = new ConfigurationBuilder()
.jmxStatistics().enable() //Enable JMX statistics
.clustering().cacheMode(CacheMode.LOCAL) //Set Cache mode to LOCAL - Data is not replicated.
.transaction().transactionMode(TransactionMode.TRANSACTIONAL).autoCommit(false) //Enable Transactional mode with autocommit false
.lockingMode(LockingMode.OPTIMISTIC).transactionManagerLookup(new GenericTransactionManagerLookup()) //uses GenericTransactionManagerLookup - This is a lookup class that locate transaction managers in the most popular Java EE application servers. If no transaction manager can be found, it defaults on the dummy transaction manager.
.locking().isolationLevel(IsolationLevel.REPEATABLE_READ) //Sets the isolation level of locking
.eviction().maxEntries(4).strategy(EvictionStrategy.LIRS) //Sets 4 as maximum number of entries in a cache instance and uses the LIRS strategy - an efficient low inter-reference recency set replacement policy to improve buffer cache performance
.persistence().passivation(false).addSingleFileStore().purgeOnStartup(true) //Disable passivation and adds a SingleFileStore that is purged on Startup
.build(); //Builds the Configuration object
manager = new DefaultCacheManager(glob, loc, true);
log.info("=== Using DefaultCacheManager (library mode) ===");
}
return manager;
}
@PreDestroy
public void cleanUp() {
manager.stop();
manager = null;
}
}
2. 事务是如何保证的?
@Model
public class CarManager {
private Logger log = Logger.getLogger(this.getClass().getName());
public static final String CACHE_NAME = "carcache";
public static final String CAR_NUMBERS_KEY = "carnumbers";
@Inject
private CacheContainerProvider provider;
/*
* Injects the javax.transaction.UserTransaction - The TransactionManager lookup is configured on
* JBossASCacheContainerProvider/TomcatCacheContainerProvider impl classes for CacheContainerProvider
*/
@Inject
private UserTransaction utx;
private BasicCache carCache;
private String carId;
private Car car = new Car();
public CarManager() {
}
public String addNewCar() {
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
List carNumbers = getNumberPlateList(carCache);
carNumbers.add(car.getNumberPlate());
carCache.put(CAR_NUMBERS_KEY, carNumbers);
carCache.put(CarManager.encode(car.getNumberPlate()), car);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return "home";
}
public String addNewCarWithRollback() {
boolean throwInducedException = true;
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
List carNumbers = getNumberPlateList(carCache);
carNumbers.add(car.getNumberPlate());
// store the new list of car numbers and then throw an exception -> roll-back
// the car number list should not be stored in the cache
carCache.put(CAR_NUMBERS_KEY, carNumbers);
if (throwInducedException)
throw new RuntimeException("Induced exception");
carCache.put(CarManager.encode(car.getNumberPlate()), car);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
log.info("Rolled back due to: " + e.getMessage());
} catch (Exception e1) {
}
}
}
return "home";
}
/**
* Operate on a clone of car number list so that we can demonstrate transaction roll-back.
*/
@SuppressWarnings("unchecked")
private List getNumberPlateList(BasicCache carCacheLoc) {
List result = null;
List carNumberList = (List) carCacheLoc.get(CAR_NUMBERS_KEY);
if (carNumberList == null) {
result = new LinkedList();
} else {
result = new LinkedList(carNumberList);
}
return result;
}
public String showCarDetails(String numberPlate) {
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
this.car = (Car) carCache.get(encode(numberPlate));
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return "showdetails";
}
public List getCarList() {
List result = null;
try {
utx.begin();
// retrieve a cache
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
// retrieve a list of number plates from the cache
result = getNumberPlateList(carCache);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return result;
}
public String removeCar(String numberPlate) {
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
carCache.remove(encode(numberPlate));
List carNumbers = getNumberPlateList(carCache);
carNumbers.remove(numberPlate);
carCache.put(CAR_NUMBERS_KEY, carNumbers);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return null;
}
public void setCarId(String carId) {
this.carId = carId;
}
public String getCarId() {
return carId;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public static String encode(String key) {
try {
return URLEncoder.encode(key, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String decode(String key) {
try {
return URLDecoder.decode(key, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
Carmart(Transactional)与Carmart基本一样,但是多了事务,不同于数据库事务,这里是内存级的事务。
Carmart(Transactional)只能运行在library mode下,因为目前只有library mode支持事务。
学习重点:
1. 事务是如何配置开启的?
@ApplicationScoped
public class JBossASCacheContainerProvider implements CacheContainerProvider {
private Logger log = Logger.getLogger(this.getClass().getName());
private BasicCacheContainer manager;
public BasicCacheContainer getCacheContainer() {
if (manager == null) {
GlobalConfiguration glob = new GlobalConfigurationBuilder()
.nonClusteredDefault() //Helper method that gets you a default constructed GlobalConfiguration, preconfigured for use in LOCAL mode
.globalJmxStatistics().enable() //This method allows enables the jmx statistics of the global configuration.
.jmxDomain("org.infinispan.carmart.tx") //prevent collision with non-transactional carmart
.build(); //Builds the GlobalConfiguration object
Configuration loc = new ConfigurationBuilder()
.jmxStatistics().enable() //Enable JMX statistics
.clustering().cacheMode(CacheMode.LOCAL) //Set Cache mode to LOCAL - Data is not replicated.
.transaction().transactionMode(TransactionMode.TRANSACTIONAL).autoCommit(false) //Enable Transactional mode with autocommit false
.lockingMode(LockingMode.OPTIMISTIC).transactionManagerLookup(new GenericTransactionManagerLookup()) //uses GenericTransactionManagerLookup - This is a lookup class that locate transaction managers in the most popular Java EE application servers. If no transaction manager can be found, it defaults on the dummy transaction manager.
.locking().isolationLevel(IsolationLevel.REPEATABLE_READ) //Sets the isolation level of locking
.eviction().maxEntries(4).strategy(EvictionStrategy.LIRS) //Sets 4 as maximum number of entries in a cache instance and uses the LIRS strategy - an efficient low inter-reference recency set replacement policy to improve buffer cache performance
.persistence().passivation(false).addSingleFileStore().purgeOnStartup(true) //Disable passivation and adds a SingleFileStore that is purged on Startup
.build(); //Builds the Configuration object
manager = new DefaultCacheManager(glob, loc, true);
log.info("=== Using DefaultCacheManager (library mode) ===");
}
return manager;
}
@PreDestroy
public void cleanUp() {
manager.stop();
manager = null;
}
}
2. 事务是如何保证的?
@Model
public class CarManager {
private Logger log = Logger.getLogger(this.getClass().getName());
public static final String CACHE_NAME = "carcache";
public static final String CAR_NUMBERS_KEY = "carnumbers";
@Inject
private CacheContainerProvider provider;
/*
* Injects the javax.transaction.UserTransaction - The TransactionManager lookup is configured on
* JBossASCacheContainerProvider/TomcatCacheContainerProvider impl classes for CacheContainerProvider
*/
@Inject
private UserTransaction utx;
private BasicCache
private String carId;
private Car car = new Car();
public CarManager() {
}
public String addNewCar() {
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
List
carNumbers.add(car.getNumberPlate());
carCache.put(CAR_NUMBERS_KEY, carNumbers);
carCache.put(CarManager.encode(car.getNumberPlate()), car);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return "home";
}
public String addNewCarWithRollback() {
boolean throwInducedException = true;
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
List
carNumbers.add(car.getNumberPlate());
// store the new list of car numbers and then throw an exception -> roll-back
// the car number list should not be stored in the cache
carCache.put(CAR_NUMBERS_KEY, carNumbers);
if (throwInducedException)
throw new RuntimeException("Induced exception");
carCache.put(CarManager.encode(car.getNumberPlate()), car);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
log.info("Rolled back due to: " + e.getMessage());
} catch (Exception e1) {
}
}
}
return "home";
}
/**
* Operate on a clone of car number list so that we can demonstrate transaction roll-back.
*/
@SuppressWarnings("unchecked")
private List
List
List
if (carNumberList == null) {
result = new LinkedList
} else {
result = new LinkedList
}
return result;
}
public String showCarDetails(String numberPlate) {
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
this.car = (Car) carCache.get(encode(numberPlate));
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return "showdetails";
}
public List
List
try {
utx.begin();
// retrieve a cache
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
// retrieve a list of number plates from the cache
result = getNumberPlateList(carCache);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return result;
}
public String removeCar(String numberPlate) {
carCache = provider.getCacheContainer().getCache(CACHE_NAME);
try {
utx.begin();
carCache.remove(encode(numberPlate));
List
carNumbers.remove(numberPlate);
carCache.put(CAR_NUMBERS_KEY, carNumbers);
utx.commit();
} catch (Exception e) {
if (utx != null) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
}
return null;
}
public void setCarId(String carId) {
this.carId = carId;
}
public String getCarId() {
return carId;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public static String encode(String key) {
try {
return URLEncoder.encode(key, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String decode(String key) {
try {
return URLDecoder.decode(key, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
没有评论:
发表评论