一、插件机制:
Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求,完 成相关数据的动态改变。
Executor
StatementHandler
ParameterHandler
ResultSetHandler
二、插件原理:
四大对象的每个对象在创建时,都会执行 interceptorChain.pluginAll(),会经过每个插 件对象的 plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四 大对象相关方法的执行,因为要执行四大对象的方法需要经过代理。
三、在spring配置文件中注册插件
<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 插件注册 -->
<property name="plugins">
<list>
<!-- 注册分页插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
<!-- 注册执行分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property>
</bean>
<!-- 注册性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<property name="format" value="true"></property>
<property name="maxTime" value="100"></property>
</bean>
<!-- 注册乐观锁插件 -->
<bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor"></bean>
</list>
</property>
</bean>
1、分页插件:com.baomidou.mybatisplus.plugins.PaginationInterceptor
@Test
public void testPage() {
Page<Employee> page = new Page<>(1,1);
List<Employee > emps =
employeeMapper.selectPage(page, null);
System.out.println(emps);
System.out.println("总条数:" +page.getTotal());
System.out.println("当前页码: "+ page.getCurrent());
System.out.println("总页码:" + page.getPages());
System.out.println("每页显示的条数:" + page.getSize());
System.out.println("是否有上一页: " + page.hasPrevious());
System.out.println("是否有下一页: " + page.hasNext());
//将查询的结果封装到page对象中
page.setRecords(emps);
}
控制台输出:
Preparing: SELECT COUNT(1) FROM tbl_employee
Parameters:
Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee LIMIT 0,1
Parameters:
Total: 1
Time:6 ms - ID:com.atguigu.mp.mapper.EmployeeMapper.selectPage
Execute SQL:
SELECT
id AS id,
last_name AS lastName,
email,
gender,
age
FROM
tbl_employee LIMIT 0,
1]
[Employee{, id=7, lastName=王五, [email protected], gender=0, age=null}]
总条数:3
当前页码: 1
总页码:3
每页显示的条数:1
是否有上一页: false
是否有下一页: true
原理分析:
@Intercepts({@Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class, Integer.class}
)})
public class PaginationInterceptor extends SqlParserHandler implements Interceptor {
private static final Log logger = LogFactory.getLog(PaginationInterceptor.class);
private ISqlParser sqlParser;
private boolean overflowCurrent = false;
private String dialectType;
private String dialectClazz;
private boolean localPage = false;
public PaginationInterceptor() {
}
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler)PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
this.sqlParser(metaObject);
MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
return invocation.proceed();
} else {
RowBounds rowBounds = (RowBounds)metaObject.getValue("delegate.rowBounds");
if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
if (!this.localPage) {
return invocation.proceed();
}
rowBounds = PageHelper.getPagination();
if (rowBounds == null) {
return invocation.proceed();
}
}
BoundSql boundSql = (BoundSql)metaObject.getValue("delegate.boundSql");
String originalSql = boundSql.getSql();
Connection connection = (Connection)invocation.getArgs()[0];
DBType dbType = StringUtils.isNotEmpty(this.dialectType) ? DBType.getDBType(this.dialectType) : JdbcUtils.getDbType(connection.getMetaData().getURL());
if (rowBounds instanceof Pagination) {
Pagination page = (Pagination)rowBounds;
boolean orderBy = true;
if (page.isSearchCount()) {
SqlInfo sqlInfo = SqlUtils.getOptimizeCountSql(page.isOptimizeCountSql(), this.sqlParser, originalSql);
orderBy = sqlInfo.isOrderBy();
this.queryTotal(this.overflowCurrent, sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
if (page.getTotal() <= 0L) {
return invocation.proceed();
}
}
String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
originalSql = DialectFactory.buildPaginationSql(page, buildSql, dbType, this.dialectClazz);
} else {
originalSql = DialectFactory.buildPaginationSql((RowBounds)rowBounds, originalSql, dbType, this.dialectClazz);
}
metaObject.setValue("delegate.boundSql.sql", originalSql);
metaObject.setValue("delegate.rowBounds.offset", 0);
metaObject.setValue("delegate.rowBounds.limit", 2147483647);
return invocation.proceed();
}
}
protected void queryTotal(boolean overflowCurrent, String sql, MappedStatement mappedStatement, BoundSql boundSql, Pagination page, Connection connection) {
try {
PreparedStatement statement = connection.prepareStatement(sql);
Throwable var8 = null;
try {
DefaultParameterHandler parameterHandler = new MybatisDefaultParameterHandler(mappedStatement, boundSql.getParameterObject(), boundSql);
parameterHandler.setParameters(statement);
long total = 0L;
ResultSet resultSet = statement.executeQuery();
Throwable var13 = null;
try {
if (resultSet.next()) {
total = resultSet.getLong(1);
}
} catch (Throwable var38) {
var13 = var38;
throw var38;
} finally {
if (resultSet != null) {
if (var13 != null) {
try {
resultSet.close();
} catch (Throwable var37) {
var13.addSuppressed(var37);
}
} else {
resultSet.close();
}
}
}
page.setTotal(total);
long pages = page.getPages();
if (overflowCurrent && (long)page.getCurrent() > pages) {
page.setCurrent(1);
}
} catch (Throwable var40) {
var8 = var40;
throw var40;
} finally {
if (statement != null) {
if (var8 != null) {
try {
statement.close();
} catch (Throwable var36) {
var8.addSuppressed(var36);
}
} else {
statement.close();
}
}
}
} catch (Exception var42) {
logger.error("Error: Method queryTotal execution error !", var42);
}
}
public Object plugin(Object target) {
return target instanceof StatementHandler ? Plugin.wrap(target, this) : target;
}
public void setProperties(Properties prop) {
String dialectType = prop.getProperty("dialectType");
String dialectClazz = prop.getProperty("dialectClazz");
String localPage = prop.getProperty("localPage");
if (StringUtils.isNotEmpty(dialectType)) {
this.dialectType = dialectType;
}
if (StringUtils.isNotEmpty(dialectClazz)) {
this.dialectClazz = dialectClazz;
}
if (StringUtils.isNotEmpty(localPage)) {
this.localPage = Boolean.valueOf(localPage);
}
}
public PaginationInterceptor setDialectType(String dialectType) {
this.dialectType = dialectType;
return this;
}
public PaginationInterceptor setDialectClazz(String dialectClazz) {
this.dialectClazz = dialectClazz;
return this;
}
public PaginationInterceptor setOverflowCurrent(boolean overflowCurrent) {
this.overflowCurrent = overflowCurrent;
return this;
}
public PaginationInterceptor setSqlParser(ISqlParser sqlParser) {
this.sqlParser = sqlParser;
return this;
}
public PaginationInterceptor setLocalPage(boolean localPage) {
this.localPage = localPage;
return this;
}
}
2、执行分析插件:com.baomidou.mybatisplus.plugins.SqlExplainInterceptor
SQL 执行分析拦截器,只支持 MySQL5.6.3 以上版本。
该插件的作用是分析 DELETE UPDATE 语句,防止 DELETE UPDATE 全表操作。
只建议在开发环境中使用,不建议在生产环境使用。
在插件的底层通过 SQL 语句分析命令:Explain 分析当前的 SQL 语句,根据结果集中的 Extra 列来断定当前是否全表操作。
@Test
public void testSQLExplain() {
employeeMapper.delete(null);
}
控制台输出:
原理分析:
@Intercepts({@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class}
)})
public class SqlExplainInterceptor implements Interceptor {
private static final Log logger = LogFactory.getLog(SqlExplainInterceptor.class);
private final String minMySQLVersion = "5.6.3";
private boolean stopProceed = false;
public SqlExplainInterceptor() {
}
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement ms = (MappedStatement)invocation.getArgs()[0];
if (ms.getSqlCommandType() == SqlCommandType.DELETE || ms.getSqlCommandType() == SqlCommandType.UPDATE) {
Executor executor = (Executor)invocation.getTarget();
Configuration configuration = ms.getConfiguration();
Object parameter = invocation.getArgs()[1];
BoundSql boundSql = ms.getBoundSql(parameter);
Connection connection = executor.getTransaction().getConnection();
String databaseVersion = connection.getMetaData().getDatabaseProductVersion();
if (GlobalConfigUtils.getDbType(configuration).equals(DBType.MYSQL) && VersionUtils.compare("5.6.3", databaseVersion)) {
logger.warn("Warn: Your mysql version needs to be greater than '5.6.3' to execute of Sql Explain!");
return invocation.proceed();
}
//执行sql分析方法
this.sqlExplain(configuration, ms, boundSql, connection, parameter);
}
return invocation.proceed();
}
protected void sqlExplain(Configuration configuration, MappedStatement mappedStatement, BoundSql boundSql, Connection connection, Object parameter) {
StringBuilder explain = new StringBuilder("EXPLAIN ");
explain.append(boundSql.getSql());
String sqlExplain = explain.toString();
StaticSqlSource sqlsource = new StaticSqlSource(configuration, sqlExplain, boundSql.getParameterMappings());
Builder builder = new Builder(configuration, "explain_sql", sqlsource, SqlCommandType.SELECT);
builder.resultMaps(mappedStatement.getResultMaps()).resultSetType(mappedStatement.getResultSetType()).statementType(mappedStatement.getStatementType());
MappedStatement queryStatement = builder.build();
DefaultParameterHandler handler = new DefaultParameterHandler(queryStatement, parameter, boundSql);
try {
PreparedStatement stmt = connection.prepareStatement(sqlExplain);
Throwable var13 = null;
try {
handler.setParameters(stmt);
ResultSet rs = stmt.executeQuery();
Throwable var15 = null;
try {
while(rs.next()) {
if (!"Using where".equals(rs.getString("Extra"))) {
if (this.isStopProceed()) {
throw new MybatisPlusException("Error: Full table operation is prohibited. SQL: " + boundSql.getSql());
}
break;
}
}
} catch (Throwable var40) {
var15 = var40;
throw var40;
} finally {
if (rs != null) {
if (var15 != null) {
try {
rs.close();
} catch (Throwable var39) {
var15.addSuppressed(var39);
}
} else {
rs.close();
}
}
}
} catch (Throwable var42) {
var13 = var42;
throw var42;
} finally {
if (stmt != null) {
if (var13 != null) {
try {
stmt.close();
} catch (Throwable var38) {
var13.addSuppressed(var38);
}
} else {
stmt.close();
}
}
}
} catch (Exception var44) {
throw new MybatisPlusException(var44);
}
}
public Object plugin(Object target) {
return target instanceof Executor ? Plugin.wrap(target, this) : target;
}
public void setProperties(Properties prop) {
String stopProceed = prop.getProperty("stopProceed");
if (StringUtils.isNotEmpty(stopProceed)) {
this.stopProceed = Boolean.valueOf(stopProceed);
}
}
public boolean isStopProceed() {
return this.stopProceed;
}
public void setStopProceed(boolean stopProceed) {
this.stopProceed = stopProceed;
}
}
3、性能分析插件:com.baomidou.mybatisplus.plugins.PerformanceInterceptor
性能分析拦截器,用于输出每条 SQL 语句及其执行时间。
SQL 性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题。
@Test
public void testPerformance() {
Employee employee = new Employee();
employee.setLastName("王五");
employee.setEmail("[email protected]");
employee.setGender("0");
employee.setAge(22);
employeeMapper.insert(employee);
}
控制台输出:
Preparing: INSERT INTO tbl_employee ( last_name, email, gender, age ) VALUES ( ?, ?, ?, ? )
Parameters: 王五(String), [email protected](String), 0(String), 22(Integer)
Updates: 1
Time:52 ms - ID:com.atguigu.mp.mapper.EmployeeMapper.insert
Execute SQL:
INSERT
INTO
tbl_employee
( last_name, email, gender, age )
VALUES
( '王五', '[email protected]', '0', 22 )]
原理分析:
@Intercepts({@Signature(
type = StatementHandler.class,
method = "query",
args = {Statement.class, ResultHandler.class}
), @Signature(
type = StatementHandler.class,
method = "update",
args = {Statement.class}
), @Signature(
type = StatementHandler.class,
method = "batch",
args = {Statement.class}
)})
public class PerformanceInterceptor implements Interceptor {
private static final Log logger = LogFactory.getLog(PerformanceInterceptor.class);
private static final String DruidPooledPreparedStatement = "com.alibaba.druid.pool.DruidPooledPreparedStatement";
private static final String T4CPreparedStatement = "oracle.jdbc.driver.T4CPreparedStatement";
private static final String OraclePreparedStatementWrapper = "oracle.jdbc.driver.OraclePreparedStatementWrapper";
private long maxTime = 0L;
private boolean format = false;
private boolean writeInLog = false;
private Method oracleGetOriginalSqlMethod;
private Method druidGetSQLMethod;
public PerformanceInterceptor() {
}
public Object intercept(Invocation invocation) throws Throwable {
Object firstArg = invocation.getArgs()[0];
Statement statement;
if (Proxy.isProxyClass(firstArg.getClass())) {
statement = (Statement)SystemMetaObject.forObject(firstArg).getValue("h.statement");
} else {
statement = (Statement)firstArg;
}
MetaObject stmtMetaObj = SystemMetaObject.forObject(statement);
try {
statement = (Statement)stmtMetaObj.getValue("stmt.statement");
} catch (Exception var20) {
;
}
if (stmtMetaObj.hasGetter("delegate")) {
try {
statement = (Statement)stmtMetaObj.getValue("delegate");
} catch (Exception var19) {
;
}
}
String originalSql = null;
String stmtClassName = statement.getClass().getName();
Class clazz;
Object stmtSql;
if ("com.alibaba.druid.pool.DruidPooledPreparedStatement".equals(stmtClassName)) {
try {
if (this.druidGetSQLMethod == null) {
clazz = Class.forName("com.alibaba.druid.pool.DruidPooledPreparedStatement");
this.druidGetSQLMethod = clazz.getMethod("getSql");
}
stmtSql = this.druidGetSQLMethod.invoke(statement);
if (stmtSql != null && stmtSql instanceof String) {
originalSql = (String)stmtSql;
}
} catch (Exception var18) {
;
}
} else if ("oracle.jdbc.driver.T4CPreparedStatement".equals(stmtClassName) || "oracle.jdbc.driver.OraclePreparedStatementWrapper".equals(stmtClassName)) {
try {
if (this.oracleGetOriginalSqlMethod != null) {
stmtSql = this.oracleGetOriginalSqlMethod.invoke(statement);
if (stmtSql != null && stmtSql instanceof String) {
originalSql = (String)stmtSql;
}
} else {
clazz = Class.forName(stmtClassName);
this.oracleGetOriginalSqlMethod = this.getMethodRegular(clazz, "getOriginalSql");
if (this.oracleGetOriginalSqlMethod != null) {
this.oracleGetOriginalSqlMethod.setAccessible(true);
if (this.oracleGetOriginalSqlMethod != null) {
Object stmtSql = this.oracleGetOriginalSqlMethod.invoke(statement);
if (stmtSql != null && stmtSql instanceof String) {
originalSql = (String)stmtSql;
}
}
}
}
} catch (Exception var17) {
;
}
}
if (originalSql == null) {
originalSql = statement.toString();
}
originalSql = originalSql.replaceAll("[\\s]+", " ");
int index = this.indexOfSqlStart(originalSql);
if (index > 0) {
originalSql = originalSql.substring(index, originalSql.length());
}
long start = SystemClock.now();
Object result = invocation.proceed();
long timing = SystemClock.now() - start;
Object target = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(target);
MappedStatement ms = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
StringBuilder formatSql = new StringBuilder();
formatSql.append(" Time:").append(timing);
formatSql.append(" ms - ID:").append(ms.getId());
formatSql.append("\n Execute SQL:").append(SqlUtils.sqlFormat(originalSql, this.format)).append("\n");
if (this.isWriteInLog()) {
if (this.getMaxTime() >= 1L && timing > this.getMaxTime()) {
logger.error(formatSql.toString());
} else {
logger.debug(formatSql.toString());
}
} else {
System.err.println(formatSql.toString());
if (this.getMaxTime() >= 1L && timing > this.getMaxTime()) {
throw new MybatisPlusException(" The SQL execution time is too large, please optimize ! ");
}
}
return result;
}
public Object plugin(Object target) {
return target instanceof StatementHandler ? Plugin.wrap(target, this) : target;
}
public void setProperties(Properties prop) {
String maxTime = prop.getProperty("maxTime");
String format = prop.getProperty("format");
if (StringUtils.isNotEmpty(maxTime)) {
this.maxTime = Long.parseLong(maxTime);
}
if (StringUtils.isNotEmpty(format)) {
this.format = Boolean.valueOf(format);
}
}
public long getMaxTime() {
return this.maxTime;
}
public PerformanceInterceptor setMaxTime(long maxTime) {
this.maxTime = maxTime;
return this;
}
public boolean isFormat() {
return this.format;
}
public PerformanceInterceptor setFormat(boolean format) {
this.format = format;
return this;
}
public boolean isWriteInLog() {
return this.writeInLog;
}
public PerformanceInterceptor setWriteInLog(boolean writeInLog) {
this.writeInLog = writeInLog;
return this;
}
public Method getMethodRegular(Class<?> clazz, String methodName) {
if (Object.class.equals(clazz)) {
return null;
} else {
Method[] arr$ = clazz.getDeclaredMethods();
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; ++i$) {
Method method = arr$[i$];
if (method.getName().equals(methodName)) {
return method;
}
}
return this.getMethodRegular(clazz.getSuperclass(), methodName);
}
}
private int indexOfSqlStart(String sql) {
String upperCaseSql = sql.toUpperCase();
Set<Integer> set = new HashSet();
set.add(upperCaseSql.indexOf("SELECT "));
set.add(upperCaseSql.indexOf("UPDATE "));
set.add(upperCaseSql.indexOf("INSERT "));
set.add(upperCaseSql.indexOf("DELETE "));
set.remove(-1);
if (CollectionUtils.isEmpty(set)) {
return -1;
} else {
List<Integer> list = new ArrayList(set);
Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
return (Integer)list.get(0);
}
}
}
4、乐观锁插件:com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor
1、 如果想实现如下需求: 当要更新一条记录的时候,希望这条记录没有被别人更新。
2、乐观锁的实现原理:
取出记录时,获取当前version
更新时,带上这个version
执行更新时,set version = yourVersion+1 where version = yourVersion
如果 version 不对,就更新失败
3、@Version 用于注解实体字段,必须要有。
测试:
在实体Employee添加version属性:
@Version
private Integer version ;
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
在表tbl_employee添加version字段:
@Test
public void testOptimisticLocker() {
Employee employee = new Employee();
employee.setId(7);
employee.setLastName("王五");
employee.setEmail("[email protected]");
employee.setGender("0");
employee.setAge(22);
employee.setVersion(1);
employeeMapper.updateById(employee);
}
控制台输出:
Preparing: UPDATE tbl_employee SET last_name=?, email=?, gender=?, age=?, version=? WHERE id=? and version=?
Parameters: 王五(String), [email protected](String), 0(String), 22(Integer), 2(Integer), 7(Integer), 1(Integer)
Updates: 1
Time:33 ms - ID:com.atguigu.mp.mapper.EmployeeMapper.updateById
Execute SQL:
UPDATE
tbl_employee
SET
last_name='王五',
email='[email protected]',
gender='0',
age=22,
version=2
WHERE
id=7
and version=1]
原理分析:
@Intercepts({@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class}
)})
public class OptimisticLockerInterceptor implements Interceptor {
private final Map<Class<?>, EntityField> versionFieldCache = new ConcurrentHashMap();
private final Map<Class<?>, List<EntityField>> entityFieldsCache = new ConcurrentHashMap();
private static final String MP_OPTLOCK_VERSION_ORIGINAL = "MP_OPTLOCK_VERSION_ORIGINAL";
private static final String MP_OPTLOCK_VERSION_COLUMN = "MP_OPTLOCK_VERSION_COLUMN";
public static final String MP_OPTLOCK_ET_ORIGINAL = "MP_OPTLOCK_ET_ORIGINAL";
private static final String NAME_ENTITY = "et";
private static final String NAME_ENTITY_WRAPPER = "ew";
private static final String PARAM_UPDATE_METHOD_NAME = "update";
public OptimisticLockerInterceptor() {
}
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement)args[0];
if (SqlCommandType.UPDATE != ms.getSqlCommandType()) {
return invocation.proceed();
} else {
Object param = args[1];
if (param instanceof HashMap) {
HashMap map = (HashMap)param;
Wrapper ew = null;
if (map.containsKey("ew")) {
ew = (Wrapper)map.get("ew");
}
Object et = null;
if (map.containsKey("et")) {
et = map.get("et");
}
if (ew != null) {
Object entity = ew.getEntity();
if (entity != null) {
Class<?> entityClass = ClassUtils.getUserClass(entity.getClass());
EntityField ef = this.getVersionField(entityClass);
Field versionField = ef == null ? null : ef.getField();
if (versionField != null) {
Object originalVersionVal = versionField.get(entity);
if (originalVersionVal != null) {
versionField.set(et, this.getUpdatedVersionVal(originalVersionVal));
}
}
}
} else if (et != null) {
String methodId = ms.getId();
String updateMethodName = methodId.substring(ms.getId().lastIndexOf(".") + 1);
if ("update".equals(updateMethodName)) {
return invocation.proceed();
}
Class<?> entityClass = ClassUtils.getUserClass(et.getClass());
EntityField entityField = this.getVersionField(entityClass);
Field versionField = entityField == null ? null : entityField.getField();
Object originalVersionVal;
if (versionField != null && (originalVersionVal = versionField.get(et)) != null) {
TableInfo tableInfo;
for(tableInfo = TableInfoHelper.getTableInfo(entityClass); null == tableInfo && null != entityClass; tableInfo = TableInfoHelper.getTableInfo(entityClass)) {
entityClass = ClassUtils.getUserClass(entityClass.getSuperclass());
}
Map<String, Object> entityMap = new HashMap();
List<EntityField> fields = this.getEntityFields(entityClass);
Iterator i$ = fields.iterator();
while(i$.hasNext()) {
EntityField ef = (EntityField)i$.next();
Field fd = ef.getField();
if (fd.isAccessible()) {
entityMap.put(fd.getName(), fd.get(et));
if (ef.isVersion()) {
versionField = fd;
}
}
}
String versionPropertyName = versionField.getName();
List<TableFieldInfo> fieldList = tableInfo.getFieldList();
String versionColumnName = entityField.getColumnName();
if (versionColumnName == null) {
Iterator i$ = fieldList.iterator();
while(i$.hasNext()) {
TableFieldInfo tf = (TableFieldInfo)i$.next();
if (versionPropertyName.equals(tf.getProperty())) {
versionColumnName = tf.getColumn();
}
}
}
if (versionColumnName != null) {
entityField.setColumnName(versionColumnName);
entityMap.put(versionField.getName(), this.getUpdatedVersionVal(originalVersionVal));
entityMap.put("MP_OPTLOCK_VERSION_ORIGINAL", originalVersionVal);
entityMap.put("MP_OPTLOCK_VERSION_COLUMN", versionColumnName);
entityMap.put("MP_OPTLOCK_ET_ORIGINAL", et);
map.put("et", entityMap);
}
}
}
}
return invocation.proceed();
}
}
protected Object getUpdatedVersionVal(Object originalVersionVal) {
Class<?> versionValClass = originalVersionVal.getClass();
if (Long.TYPE.equals(versionValClass)) {
return (Long)originalVersionVal + 1L;
} else if (Long.class.equals(versionValClass)) {
return (Long)originalVersionVal + 1L;
} else if (Integer.TYPE.equals(versionValClass)) {
return (Integer)originalVersionVal + 1;
} else if (Integer.class.equals(versionValClass)) {
return (Integer)originalVersionVal + 1;
} else if (Date.class.equals(versionValClass)) {
return new Date();
} else {
return Timestamp.class.equals(versionValClass) ? new Timestamp(System.currentTimeMillis()) : originalVersionVal;
}
}
public Object plugin(Object target) {
return target instanceof Executor ? Plugin.wrap(target, this) : target;
}
public void setProperties(Properties properties) {
}
private EntityField getVersionField(Class<?> parameterClass) {
synchronized(parameterClass.getName()) {
if (this.versionFieldCache.containsKey(parameterClass)) {
return (EntityField)this.versionFieldCache.get(parameterClass);
} else {
EntityField field = this.getVersionFieldRegular(parameterClass);
if (field != null) {
this.versionFieldCache.put(parameterClass, field);
return field;
} else {
return null;
}
}
}
}
private EntityField getVersionFieldRegular(Class<?> parameterClass) {
if (parameterClass != Object.class) {
Field[] arr$ = parameterClass.getDeclaredFields();
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; ++i$) {
Field field = arr$[i$];
if (field.isAnnotationPresent(Version.class)) {
field.setAccessible(true);
return new EntityField(field, true);
}
}
return this.getVersionFieldRegular(parameterClass.getSuperclass());
} else {
return null;
}
}
private List<EntityField> getEntityFields(Class<?> parameterClass) {
if (this.entityFieldsCache.containsKey(parameterClass)) {
return (List)this.entityFieldsCache.get(parameterClass);
} else {
List<EntityField> fields = this.getFieldsFromClazz(parameterClass, (List)null);
this.entityFieldsCache.put(parameterClass, fields);
return fields;
}
}
private List<EntityField> getFieldsFromClazz(Class<?> parameterClass, List<EntityField> fieldList) {
if (fieldList == null) {
fieldList = new ArrayList();
}
List<Field> fields = ReflectionKit.getFieldList(parameterClass);
Iterator i$ = fields.iterator();
while(i$.hasNext()) {
Field field = (Field)i$.next();
field.setAccessible(true);
if (field.isAnnotationPresent(Version.class)) {
((List)fieldList).add(new EntityField(field, true));
} else {
((List)fieldList).add(new EntityField(field, false));
}
}
return (List)fieldList;
}
}