|
@ -1,8 +1,6 @@
|
|
package com.yihu.jw.util.sql;
|
|
package com.yihu.jw.util.sql;
|
|
|
|
|
|
import org.hibernate.transform.ResultTransformer;
|
|
|
|
|
|
|
|
import javax.persistence.Column;
|
|
|
|
import java.beans.BeanInfo;
|
|
import java.beans.BeanInfo;
|
|
import java.beans.IntrospectionException;
|
|
import java.beans.IntrospectionException;
|
|
import java.beans.Introspector;
|
|
import java.beans.Introspector;
|
|
@ -11,19 +9,21 @@ import java.lang.reflect.Field;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Method;
|
|
import java.sql.SQLException;
|
|
import java.sql.SQLException;
|
|
|
|
import java.sql.Time;
|
|
import java.sql.Timestamp;
|
|
import java.sql.Timestamp;
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
import javax.persistence.Column;
|
|
|
|
import org.hibernate.transform.ResultTransformer;
|
|
|
|
|
|
/**
|
|
|
|
* @created Airhead 2015/12/26.
|
|
|
|
*/
|
|
|
|
public class BeanTransformer<T> implements ResultTransformer {
|
|
public class BeanTransformer<T> implements ResultTransformer {
|
|
private final Class<T> mapClass;
|
|
private final Class<T> mapClass;
|
|
public Map<String, String> columnToProperty;
|
|
public Map<String, String> columnToProperty;
|
|
public Map<String, String> propertyToColumn;
|
|
public Map<String, String> propertyToColumn;
|
|
|
|
|
|
public BeanTransformer(Class<T> mapClass) {
|
|
public BeanTransformer(Class<T> mapClass) {
|
|
this.mapClass = mapClass;
|
|
this.mapClass = mapClass;
|
|
this.initColumnsToProperties();
|
|
this.initColumnsToProperties();
|
|
@ -34,17 +34,13 @@ public class BeanTransformer<T> implements ResultTransformer {
|
|
try {
|
|
try {
|
|
PropertyDescriptor[] props = this.propertyDescriptors();
|
|
PropertyDescriptor[] props = this.propertyDescriptors();
|
|
int[] col2Pro = this.mapColumnsToProperties(aliases, props);
|
|
int[] col2Pro = this.mapColumnsToProperties(aliases, props);
|
|
|
|
|
|
return this.createBean(tuple, mapClass, props, col2Pro);
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
return this.createBean(tuple, this.mapClass, props, col2Pro);
|
|
|
|
} catch (Exception var5) {
|
|
|
|
var5.printStackTrace();
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
|
|
public List transformList(List list) {
|
|
public List transformList(List list) {
|
|
return list;
|
|
return list;
|
|
}
|
|
}
|
|
@ -52,21 +48,21 @@ public class BeanTransformer<T> implements ResultTransformer {
|
|
protected T newInstance(Class<T> c) throws Exception {
|
|
protected T newInstance(Class<T> c) throws Exception {
|
|
try {
|
|
try {
|
|
return c.newInstance();
|
|
return c.newInstance();
|
|
} catch (InstantiationException | IllegalAccessException e) {
|
|
|
|
throw new Exception("Cannot create " + c.getName() + ": " + e.getMessage());
|
|
|
|
|
|
} catch (IllegalAccessException | InstantiationException var3) {
|
|
|
|
throw new Exception("Cannot create " + c.getName() + ": " + var3.getMessage());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
protected int[] mapColumnsToProperties(String[] aliases, PropertyDescriptor[] props) throws SQLException {
|
|
protected int[] mapColumnsToProperties(String[] aliases, PropertyDescriptor[] props) throws SQLException {
|
|
int[] col2Pro = new int[aliases.length];
|
|
int[] col2Pro = new int[aliases.length];
|
|
Arrays.fill(col2Pro, -1);
|
|
Arrays.fill(col2Pro, -1);
|
|
|
|
|
|
for (int col = 0; col < aliases.length; ++col) {
|
|
|
|
|
|
for(int col = 0; col < aliases.length; ++col) {
|
|
String columnName = aliases[col];
|
|
String columnName = aliases[col];
|
|
String propertyName = this.columnToProperty.get(columnName.toUpperCase());
|
|
|
|
for (int i = 0; i < props.length; ++i) {
|
|
|
|
if (propertyName.equals(props[i].getName())) {
|
|
|
|
|
|
String propertyName = (String)this.columnToProperty.get(columnName.toUpperCase());
|
|
|
|
|
|
|
|
for(int i = 0; i < props.length; ++i) {
|
|
|
|
if (propertyName != null & props[i] != null && propertyName.equals(props[i].getName())) {
|
|
col2Pro[col] = i;
|
|
col2Pro[col] = i;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@ -76,11 +72,10 @@ public class BeanTransformer<T> implements ResultTransformer {
|
|
return col2Pro;
|
|
return col2Pro;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
private T createBean(Object[] tuple, Class<T> type, PropertyDescriptor[] props, int[] col2Pro) throws Exception {
|
|
private T createBean(Object[] tuple, Class<T> type, PropertyDescriptor[] props, int[] col2Pro) throws Exception {
|
|
T bean = this.newInstance(type);
|
|
T bean = this.newInstance(type);
|
|
|
|
|
|
for (int i = 0; i < col2Pro.length; ++i) {
|
|
|
|
|
|
for(int i = 0; i < col2Pro.length; ++i) {
|
|
int realIndex = col2Pro[i];
|
|
int realIndex = col2Pro[i];
|
|
if (realIndex != -1) {
|
|
if (realIndex != -1) {
|
|
Object value = tuple[i];
|
|
Object value = tuple[i];
|
|
@ -94,125 +89,113 @@ public class BeanTransformer<T> implements ResultTransformer {
|
|
|
|
|
|
private void callSetter(Object target, PropertyDescriptor prop, Object value) throws Exception {
|
|
private void callSetter(Object target, PropertyDescriptor prop, Object value) throws Exception {
|
|
Method setter = prop.getWriteMethod();
|
|
Method setter = prop.getWriteMethod();
|
|
|
|
if (setter != null) {
|
|
|
|
Class[] params = setter.getParameterTypes();
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (value instanceof Date) {
|
|
|
|
String targetType = params[0].getName();
|
|
|
|
if ("java.sql.Date".equals(targetType)) {
|
|
|
|
value = new java.sql.Date(((Date)value).getTime());
|
|
|
|
} else if ("java.sql.Time".equals(targetType)) {
|
|
|
|
value = new Time(((Date)value).getTime());
|
|
|
|
} else if ("java.sql.Timestamp".equals(targetType)) {
|
|
|
|
Timestamp tsValue = (Timestamp)value;
|
|
|
|
int nanos = tsValue.getNanos();
|
|
|
|
value = new Timestamp(tsValue.getTime());
|
|
|
|
((Timestamp)value).setNanos(nanos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (setter == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
if (this.isCompatibleType(value, params[0])) {
|
|
|
|
setter.invoke(target, value);
|
|
|
|
} else if (params[0].equals(Long.TYPE) && value instanceof Integer) {
|
|
|
|
setter.invoke(target, value);
|
|
|
|
} else {
|
|
|
|
if (!params[0].equals(Long.class) || !(value instanceof Integer)) {
|
|
|
|
throw new Exception("Cannot set " + prop.getName() + ": incompatible types, cannot convert " + value.getClass().getName() + " to " + params[0].getName());
|
|
|
|
}
|
|
|
|
|
|
Class<?>[] params = setter.getParameterTypes();
|
|
|
|
try {
|
|
|
|
// convert types for some popular ones
|
|
|
|
if (value instanceof java.util.Date) {
|
|
|
|
final String targetType = params[0].getName();
|
|
|
|
if ("java.sql.Date".equals(targetType)) {
|
|
|
|
value = new java.sql.Date(((java.util.Date) value).getTime());
|
|
|
|
} else if ("java.sql.Time".equals(targetType)) {
|
|
|
|
value = new java.sql.Time(((java.util.Date) value).getTime());
|
|
|
|
} else if ("java.sql.Timestamp".equals(targetType)) {
|
|
|
|
Timestamp tsValue = (Timestamp) value;
|
|
|
|
int nanos = tsValue.getNanos();
|
|
|
|
value = new Timestamp(tsValue.getTime());
|
|
|
|
((Timestamp) value).setNanos(nanos);
|
|
|
|
|
|
setter.invoke(target, Long.valueOf(value.toString()));
|
|
}
|
|
}
|
|
} else {
|
|
|
|
// if (value instanceof String && params[0].isEnum()) {
|
|
|
|
// value = Enum.valueOf(params[0].asSubclass(Enum.class), (String) value);
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Don't call setter if the value object isn't the right type
|
|
|
|
if (this.isCompatibleType(value, params[0])) {
|
|
|
|
setter.invoke(target, new Object[]{value});
|
|
|
|
} else {
|
|
|
|
throw new Exception(
|
|
|
|
"Cannot set " + prop.getName() + ": incompatible types, cannot convert "
|
|
|
|
+ value.getClass().getName() + " to " + params[0].getName());
|
|
|
|
// value cannot be null here because isCompatibleType allows null
|
|
|
|
|
|
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException var9) {
|
|
|
|
throw new SQLException("Cannot set " + prop.getName() + ": " + var9.getMessage());
|
|
}
|
|
}
|
|
|
|
|
|
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
|
|
|
|
throw new SQLException(
|
|
|
|
"Cannot set " + prop.getName() + ": " + e.getMessage());
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void initColumnsToProperties() {
|
|
private void initColumnsToProperties() {
|
|
columnToProperty = new HashMap<>();
|
|
|
|
Field[] fields = mapClass.getDeclaredFields();
|
|
|
|
for (Field f : fields) {
|
|
|
|
Column column = f.getAnnotation(Column.class);
|
|
|
|
if (column == null) {
|
|
|
|
continue;
|
|
|
|
|
|
this.columnToProperty = new HashMap();
|
|
|
|
Field[] fields = this.mapClass.getDeclaredFields();
|
|
|
|
Field[] var2 = fields;
|
|
|
|
int var3 = fields.length;
|
|
|
|
|
|
|
|
for(int var4 = 0; var4 < var3; ++var4) {
|
|
|
|
Field f = var2[var4];
|
|
|
|
Column column = (Column)f.getAnnotation(Column.class);
|
|
|
|
if (column != null) {
|
|
|
|
String columnName = column.name();
|
|
|
|
String propertyName = f.getName();
|
|
|
|
this.columnToProperty.put(columnName.toUpperCase(), propertyName);
|
|
}
|
|
}
|
|
|
|
|
|
String columnName = column.name();
|
|
|
|
String propertyName = f.getName();
|
|
|
|
columnToProperty.put(columnName.toUpperCase(), propertyName);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private void initPropertiesToColumns() {
|
|
private void initPropertiesToColumns() {
|
|
propertyToColumn = new HashMap<>();
|
|
|
|
Field[] fields = mapClass.getDeclaredFields();
|
|
|
|
for (Field f : fields) {
|
|
|
|
Column column = f.getAnnotation(Column.class);
|
|
|
|
if (column == null) {
|
|
|
|
continue;
|
|
|
|
|
|
this.propertyToColumn = new HashMap();
|
|
|
|
Field[] fields = this.mapClass.getDeclaredFields();
|
|
|
|
Field[] var2 = fields;
|
|
|
|
int var3 = fields.length;
|
|
|
|
|
|
|
|
for(int var4 = 0; var4 < var3; ++var4) {
|
|
|
|
Field f = var2[var4];
|
|
|
|
Column column = (Column)f.getAnnotation(Column.class);
|
|
|
|
if (column != null) {
|
|
|
|
String columnName = column.name();
|
|
|
|
String propertyName = f.getName();
|
|
|
|
this.propertyToColumn.put(propertyName, columnName.toUpperCase());
|
|
}
|
|
}
|
|
|
|
|
|
String columnName = column.name();
|
|
|
|
String propertyName = f.getName();
|
|
|
|
propertyToColumn.put(propertyName,columnName.toUpperCase());
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private PropertyDescriptor[] propertyDescriptors() throws Exception {
|
|
private PropertyDescriptor[] propertyDescriptors() throws Exception {
|
|
BeanInfo beanInfo = null;
|
|
BeanInfo beanInfo = null;
|
|
|
|
|
|
try {
|
|
try {
|
|
beanInfo = Introspector.getBeanInfo(mapClass);
|
|
|
|
} catch (IntrospectionException e) {
|
|
|
|
throw new Exception("Bean introspection failed: " + e.getMessage());
|
|
|
|
|
|
beanInfo = Introspector.getBeanInfo(this.mapClass);
|
|
|
|
} catch (IntrospectionException var3) {
|
|
|
|
throw new Exception("Bean introspection failed: " + var3.getMessage());
|
|
}
|
|
}
|
|
|
|
|
|
return beanInfo.getPropertyDescriptors();
|
|
return beanInfo.getPropertyDescriptors();
|
|
}
|
|
}
|
|
|
|
|
|
private boolean isCompatibleType(Object value, Class<?> type) {
|
|
private boolean isCompatibleType(Object value, Class<?> type) {
|
|
// Do object check first, then primitives
|
|
|
|
if (value == null || type.isInstance(value)) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Integer.TYPE) && value instanceof Integer) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Integer.TYPE) && value instanceof Long) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Long.TYPE) && value instanceof Long) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Double.TYPE) && value instanceof Double) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Float.TYPE) && value instanceof Float) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Short.TYPE) && value instanceof Short) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Byte.TYPE) && value instanceof Byte) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Character.TYPE) && value instanceof Character) {
|
|
|
|
return true;
|
|
|
|
|
|
|
|
} else if (type.equals(Boolean.TYPE) && value instanceof Boolean) {
|
|
|
|
|
|
if (value != null && !type.isInstance(value)) {
|
|
|
|
if (type.equals(Integer.TYPE) && value instanceof Integer) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Integer.TYPE) && value instanceof Long) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Long.TYPE) && value instanceof Long) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Double.TYPE) && value instanceof Double) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Float.TYPE) && value instanceof Float) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Short.TYPE) && value instanceof Short) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Byte.TYPE) && value instanceof Byte) {
|
|
|
|
return true;
|
|
|
|
} else if (type.equals(Character.TYPE) && value instanceof Character) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return type.equals(Boolean.TYPE) && value instanceof Boolean;
|
|
|
|
}
|
|
|
|
} else {
|
|
return true;
|
|
return true;
|
|
|
|
|
|
}
|
|
}
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|