我在数据库中有两个表有一对多的关系。当我获取表User时,我想将User中的数据(与Vehicle相关的数据)复制到另一个对象UserDuplicate(和VehicleDuplicate)。我尝试使用BeanUtils.copyProperties,但嵌套引用仍然引用旧对象。我想知道复制嵌套对象的方法是什么。谢谢。
import java.util.Set;
public class User {
private Set<Vehicle> vehs = new HasHSet();
public Set<Vehicle> getVehs() {
return vehs;
}
public void setVehs(Set<Vehicle> vehs) {
this.vehs = vehs;
}
}
class Vehicle {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
class UserDuplicate {
private Set<VehicleDuplicate> vehDup=new HasHSet();
public Set<VehicleDuplicate> getVehDup() {
return vehDup;
}
public void setVehDup(Set<VehicleDuplicate> vehDup) {
this.vehDup = vehDup;
}
}
class VehicleDuplicate {
private UserDuplicate userDup;
public UserDuplicate getUserDup() {
return userDup;
}
public void setUserDup(UserDuplicate userDup) {
this.userDup = userDup;
}
}
我喜欢在这些情况下使用复制构造函数:
class UserDuplicate {
...
UserDuplicate(User user) {
...
if (user.getVehs() != null) {
vehDup = new HashSet<>();
for (Vehicle v: user.getVehs()) {
vehDup.add(new VehicleDuplicate(this, v));
}
}
}
...
class VehicleDuplicate {
...
VehicleDuplicate(UserDuplicate userDup, Vehicle veh) {
this.userDup = userDup;
...
}
一种方法可能是使用映射器将所需内容复制到重复对象,这种方法可以在代码上占用更少的空间......
例如,您可以使用jackson-databind
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
UserDuplicate duplicated = mapper.readValue(mapper.writeValueAsString(source), UserDuplicate.class);
// set the correct duplicate user in the duplicated vehicule
duplicated.getVehDup().forEach(x -> x.setUserDup(duplicated));
这会将source
对象序列化为JSON,然后将其反序列化为duplicated
对象的实例。
因为您说您的模式或多或少相同,所以您可以处理杰克逊提供的注释,例如忽略某些字段。
static class User {
@JsonIgnore // Allows to ignore attributes from stadging to production
private String iDontWantToCopyThis = "blablabla";
private Set<Vehicle> vehs;
public Set<Vehicle> getVehs() {
return vehs;
}
public void setVehs(Set<Vehicle> vehs) {
this.vehs = vehs;
}
}
这样做的iDontWantToCopyThis
字段将不会被复制到重复的对象中。
因为你的Vehicle
包含对user
的引用,你需要用@JsonIgnore
注释以避免反序列化过程中的递归。
static class Vehicle {
@JsonIgnore
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
并且因为vehicule集的名称与UserDuplicate
类不同,所以必须使用注释@JsonProperty("vehs")
让映射器知道如何匹配数据。
static class UserDuplicate {
@JsonProperty("vehs") // need to specify the source name into the json used to load the user duplicated
private Set<VehicleDuplicate> vehDup;
public Set<VehicleDuplicate> getVehDup() {
return vehDup;
}
public void setVehDup(Set<VehicleDuplicate> vehDup) {
this.vehDup = vehDup;
}
}
如果您的数据转换过于复杂而无法通过注释进行处理,您还可以创建自定义序列化程序或反序列化程序......