有没有办法在实体中设置一些只包含字段列名称信息的字段?
例如:
@Entity
@Table(name = "T_PERSON")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "p_id")
private int id;
@Column(name = "p_name")
private String name;
// getters and setters for id and name
}
所以我将p_name
和T_PERSON
作为输入,我想在其中设置一些值。
我找到this和this来使用列名获取字段名称,我可以使用Reflection
来获取setter方法,但是有没有替代反射?
答案 0 :(得分:3)
我认为你最好的选择只是使用反射。 Hibernate内部也使用反射来读取通过注释完成的所有映射。如果你想试试hibernate内部类,那么看一下Hibernate的SessionFactory实现类(org.hibernate.impl.SessionFactoryImpl),它为每个实体保存包含类元数据(org.hibernate.metadata.ClassMetadata)的map。您必须在代码中引用单例SessionFactory。
您可以使用
获取ClassMeta数据public ClassMetadata getClassMetadata(Class persistentClass) throws HibernateException
ClassMetaData中的方法很少,这可能是你感兴趣的。例如,
public void setPropertyValue(Object object, String propertyName, Object value, EntityMode entityMode) throws HibernateException;
EntityMode可以指定为EntityMode.POJO
此外,如果你有一个用于初始化hibernate的Configuration对象的引用,你可以查询你感兴趣的表
public Table getTable(String schema, String catalog, String name) {
String key = Table.qualify(catalog, schema, name);
return tables.get(key);
}
并且有方法来获取物理或逻辑列名称
public String getPhysicalColumnName(String logicalName, Table table) throws MappingException
和
public String getLogicalColumnName(String physicalName, Table table) throws MappingException
答案 1 :(得分:1)
虽然我普遍同意这些评论 - 我会使用JDBCTemplate或其他类似的东西来完成你所追求的东西,你可能会研究一个字段上的@Transient注释,或者可能只是写下这样的东西:
public void setFieldForColumnName(String columnName, Object value){
Switch(columnName){
case("columnA"):
setColumnA(value);
break;
default:
// ....
break;
}
}
当然,这依赖于一个字符串开关 - 如果你没有能够打开字符串,你必须转换为if / then。
我重申,我认为这不是理想的管理方式,但如果你绝对与hibernate结婚,这将是你想做的事情的一种方式(我想)
答案 2 :(得分:1)
如果您可以控制Entity类属性名称创建,则根据表列名称创建java属性名称(例如,应用规则:规则1 - 列p_name为pName)。
在用户输入表列名称上应用规则并标识实体类属性并调用setter方法。
如果没有对Entity类属性名称的控制,那么使用反射是最好的方法。
答案 3 :(得分:1)
您可以使用以下方法运行常见的SQL更新查询:
public int updateSomeParameter(String tableName, String idColumnName, int id,
String parameterColumnName, Object newParameterValue) {
String sql = "UPDATE " + tableName + " SET " + parameterColumnName
+ " = :new_value WHERE " + idColumnName + " = :id";
SQLQuery query = session.createSQLQuery(sql);
query.setInteger("id", id);
query.setParameter("new_value", newParameterValue);
return query.executeUpdate();
}
int updateCout = updateSomeParameter("T_PERSON", "p_id", 50, "p_name", "Some New Name");
但这种方式是 高度推荐的 ,特别是如果表名和列名来自用户输入,因为它很容易引起SQL注入。
答案 4 :(得分:1)
由于在编译时不知道要调用的方法,根据我的理解,反射是唯一的方法。
如果您试图避免在调用代码中使用反射,则可以编写一个包装器方法,在内部使用反射来进行设置,然后在调用方法中使用该方法。
这样的事情:
public static <T> Map<String, java.lang.reflect.Method> obtainMapOfColumnNamesAndSetters(Class<T> classType) {
Map<String, java.lang.reflect.Method> result = null;
/*
* Use reflection to iterate over all fields and
* identify ones with annotation and build a map of database column names and fields
* and use the field names to obtain the setter method references and save it in a map and return it as result.
*
* The result map's key is the column name and the value is the method to be set.
*
* Note: Ideally, this map needs to be build only once per class.
*/
return result;
}
public static boolean genericHibernatePropertySetter(Object beanObject, Object parameterObject, String annotationValue,
Map<String, java.lang.reflect.Method> columnAndMethodMap)
{
boolean result = false;
/*
* Use this method to hide the reflection from invoking classes.
*
* Fetch the corresponding 'java.lang.reflect.Method' instance from the map.
* Use the method instance to set the parameter on the bean object.
*
*/
return result; // set to true in the implementation
}
希望这有帮助。