net.hasor.db.jdbc.mapping.BeanRowMapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hasor-db Show documentation
Show all versions of hasor-db Show documentation
the hasor DataBase project.
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.hasor.db.jdbc.mapping;
import net.hasor.db.jdbc.RowMapper;
import net.hasor.db.types.TypeHandler;
import net.hasor.db.types.TypeHandlerRegistry;
import net.hasor.db.types.UnknownTypeHandler;
import net.hasor.utils.BeanUtils;
import net.hasor.utils.ExceptionUtils;
import net.hasor.utils.StringUtils;
import net.hasor.utils.convert.ConverterUtils;
import java.sql.JDBCType;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
/**
* 用于 POJO 的 RowMapper,带有 ORM 能力
* @version : 2020-10-31
* @author 赵永春 ([email protected])
*/
public class BeanRowMapper implements RowMapper, TableInfo {
private final Class mapperClass;
private String tableName;
private boolean caseInsensitive;
//
private final Map propertyColumnMapping;
private final Map columnPropertyMapping;
private final List columnNames;
private final Map columnFieldInfoMap;
private final Map> columnTypeHandlerMap;
/** Create a new ResultMapper.*/
public BeanRowMapper(Class mapperClass) {
this(mapperClass, TypeHandlerRegistry.DEFAULT);
}
/** Create a new ResultMapper.*/
public BeanRowMapper(Class mapperClass, TypeHandlerRegistry handlerRegistry) {
this.mapperClass = mapperClass;
this.columnNames = new ArrayList<>();
this.columnFieldInfoMap = new HashMap<>();
this.columnTypeHandlerMap = new HashMap<>();
this.propertyColumnMapping = new HashMap<>();
this.columnPropertyMapping = new HashMap<>();
this.initialize(mapperClass, Objects.requireNonNull(handlerRegistry, "handlerRegistry is null."));
}
private void initialize(Class mapperClass, TypeHandlerRegistry registry) {
Table defTable = null;
if (mapperClass.isAnnotationPresent(Table.class)) {
defTable = mapperClass.getAnnotation(Table.class);
} else {
defTable = new TableImpl(mapperClass.getSimpleName());
}
this.tableName = StringUtils.isNotBlank(defTable.name()) ? defTable.name() : defTable.value();
this.caseInsensitive = defTable.caseInsensitive();
boolean autoConfigField = defTable.autoFiled();
List allFields = BeanUtils.findALLFields(mapperClass);
for (java.lang.reflect.Field field : allFields) {
Field defField = defField(field, autoConfigField);
if (defField == null) {
continue;
}
//
TypeHandler> typeHandler = null;
if (defField.typeHandler() == UnknownTypeHandler.class) {
typeHandler = registry.getTypeHandler(field.getType(), defField.jdbcType());
} else {
try {
typeHandler = defField.typeHandler().newInstance();
} catch (Exception e) {
throw ExceptionUtils.toRuntimeException(e);
}
}
this.setupField(field, defField, typeHandler);
}
}
private Field defField(java.lang.reflect.Field dtoField, boolean autoConfigField) {
if (dtoField.isAnnotationPresent(Field.class)) {
return dtoField.getAnnotation(Field.class);
} else if (autoConfigField) {
Class> fieldType = dtoField.getType();
JDBCType jdbcType = TypeHandlerRegistry.toSqlType(fieldType);
return new FieldImpl(dtoField.getName(), jdbcType);
} else {
return null;
}
}
private void setupField(java.lang.reflect.Field property, net.hasor.db.jdbc.mapping.Field defField, TypeHandler> toTypeHandler) {
String columnName = null;
JDBCType jdbcType = defField.jdbcType();
if (StringUtils.isNotBlank(defField.name())) {
columnName = defField.name();
} else {
columnName = defField.value();
}
if (StringUtils.isBlank(columnName)) {
columnName = property.getName();
}
if (jdbcType == JDBCType.OTHER) {
jdbcType = TypeHandlerRegistry.toSqlType(property.getType());
}
//
String useColumnName = columnName;
if (this.caseInsensitive) {
useColumnName = useColumnName.toUpperCase();
}
this.columnNames.add(useColumnName);
this.columnFieldInfoMap.put(useColumnName, new FieldInfoImpl(columnName, jdbcType, property.getType()));
this.columnTypeHandlerMap.put(useColumnName, toTypeHandler);
this.columnPropertyMapping.put(useColumnName, property.getName());
this.propertyColumnMapping.put(property.getName(), useColumnName);
}
public Class getMapperClass() {
return this.mapperClass;
}
public String getTableName() {
return this.tableName;
}
public boolean isCaseInsensitive() {
return this.caseInsensitive;
}
public void setCaseInsensitive(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
public FieldInfo findFieldInfoByProperty(String propertyName) {
String columnName = this.propertyColumnMapping.get(propertyName);
return this.columnFieldInfoMap.get(columnName);
}
public Collection allFieldInfoByProperty() {
return this.columnFieldInfoMap.values();
}
public TableInfo getTableInfo() {
return this;
}
@Override
public T mapRow(final ResultSet rs, final int rowNum) throws SQLException {
T targetObject;
try {
targetObject = this.mapperClass.newInstance();
return this.tranResultSet(rs, targetObject);
} catch (ReflectiveOperationException e) {
throw new SQLException(e);
}
}
private T tranResultSet(final ResultSet rs, final T targetObject) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
int nrOfColumns = rsmd.getColumnCount();
Map resultColumnMap = new HashMap<>();
for (int i = 1; i <= nrOfColumns; i++) {
String colName = rsmd.getColumnName(i);
if (this.caseInsensitive) {
resultColumnMap.put(colName.toUpperCase(), i);
} else {
resultColumnMap.put(colName, i);
}
}
//
for (String columnName : this.columnNames) {
if (!resultColumnMap.containsKey(columnName)) {
continue;
}
int realIndex = resultColumnMap.get(columnName);
TypeHandler> realHandler = this.columnTypeHandlerMap.get(columnName);
Object result = realHandler.getResult(rs, realIndex);
//
String propertyName = this.columnPropertyMapping.get(columnName);
Class> propertyType = BeanUtils.getPropertyOrFieldType(this.mapperClass, propertyName);
Object convert = ConverterUtils.convert(propertyType, result);
BeanUtils.writePropertyOrField(targetObject, propertyName, convert);
}
return targetObject;
}
/**
* Static factory method to create a new BeanPropertyRowMapper (with the mapped class specified only once).
* @param mappedClass the class that each row should be mapped to
*/
public static BeanRowMapper newInstance(final Class mappedClass) {
return MappingHandler.DEFAULT.resolveMapper(mappedClass);
}
/**
* Static factory method to create a new BeanPropertyRowMapper (with the mapped class specified only once).
* @param mappedClass the class that each row should be mapped to
*/
public static BeanRowMapper newInstance(final Class mappedClass, final TypeHandlerRegistry registry) {
return new MappingHandler(registry).resolveMapper(mappedClass);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy