我试图弄清楚如何将请求中传入的数据映射到Hibernate对象,问题是传入的数据可能是对象或子对象,字段数据不一定是已知的-表单是用户配置的,以包含和收集所需的数据。
对象大致如下:
Job {
String title;
@ManyToOne
@JoinColumn(name = "location_id")
JobLocation location;
}
JobLocation {
int id;
String description;
double latitude;
double longitude;
}
因此,如果用户已经定义他们想要编辑JobLocation描述,我们将在请求中返回
一行的内容。{ jobLocationDescription: 'Santa Fe' }
如何将其映射回我正在处理的Job
的子?在节省时间时,我所拥有的是对Job
的参考,所有其他项目可能会根据他们在下拉菜单中选择的内容而变化。一种选择是存储一个引用,如job.location.description
,并使用getter和反射来做一个进程驱动选项:
String[] field = requestField.split(".");
Entity ent = (get object from field[0]);
if (field.length > 2) {
ent = ent.get[get method name from next field position]();
}
ent.set[get method name from last field[] value](requestValue);
遗憾的是,没有什么说它不能是多层的,为了得到我们目前认为的方法,我们必须使用反射。还有其他更好的方法来做这种手术吗?还是我们只能在这个过程中挣扎?
在我们的项目中我也有类似的需求。我们最终使用反射+注释进行映射。简而言之,我们有这样的东西来构造对象。
class Job {
String title;
@ManyToOne
@JoinColumn(name = "location_id")
@EntityMapper(isRef="true")//Custom Annotation
JobLocation location;
}
class JobLocation {
@EntityMapper(fieldName="jobLocationId")
int id;
@EntityMapper(fieldName="jobLocationDescription")//Custom Annotation
String description;
double latitude;
double longitude;
}
如果你不明白我的意思,我们创建了自定义注释,并编写了一个实用程序方法,通过反射循环遍历具有注释的元素,如下所示:
for (Field field : object.getClass().getDeclaredFields()) {
//check for the EntityMapper annotation
if (field.getAnnotation(EntityMapper.class) != null) {
.
.
.//Use more reflection to use getters and setters to create and assign values from the JSON request.
}
}
如果在编译时知道要调用的方法的名称,则不必使用反射。听起来你需要反思一下。但是,这并不意味着您必须使用原始的java.lang.reflect
API,直接使用它是相当痛苦的。如果您已经在使用Spring,那么BeanWrapperImpl
是一个非常好的实用程序,它可以使用您现有的ConversionService
将您的输入转换为目标类型。否则我建议使用Commons BeanUtils,它可以做几乎相同的事情,但没有Springiness。两个库都知道如何处理嵌套属性和Map
值的属性。