Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 避免在加载时实例化存储包含null的@Embedded字段?_Java_Hibernate_Jpa_Jpa 2.1 - Fatal编程技术网

Java 避免在加载时实例化存储包含null的@Embedded字段?

Java 避免在加载时实例化存储包含null的@Embedded字段?,java,hibernate,jpa,jpa-2.1,Java,Hibernate,Jpa,Jpa 2.1,如果不带地址的人员被保留并在以后加载,人员包含一个地址,所有字段都设置为空 此(修改后的)示例取自,其中报告了类似的问题 @Embeddable public class Address { private String street; private String postalCode; } @Entity public class Person { private String name; @Embedded private Address home; } 我怎样才能

如果不带
地址的
人员
被保留并在以后加载,
人员
包含一个
地址
,所有字段都设置为

此(修改后的)示例取自,其中报告了类似的问题

@Embeddable
public class Address {
  private String street;
  private String postalCode;
}

@Entity
public class Person {
  private String name;
  @Embedded
  private Address home;
}
我怎样才能避开这个问题?如果所有字段均为
null
,是否可以指示Hibernate不要实例化嵌入的
@对象


更改每个
@Embedded
字段的getter似乎很麻烦,而且容易出错。另一个麻烦的替代方法是使用
@PostLoad
,但这只是为
@实体
调用的,而不是为
@可嵌入的
调用的。

好吧,我写了一些对我的情况有帮助的东西。我用
@PostLoad
将其添加到
@Entity
s,并使用
@embeddeble
s:

public class NullableEmbeddedCleanerImpl implements NullableEmbeddedCleaner {
    private final static Logger LOGGER = LoggerFactory.getLogger(NullableEmbeddedCleaner.class);

    Map<Class<?>, Predicate<Object>> classFilterForNullables = new HashMap<>();
    Map<Class<?>, Predicate<Object>> collectionMap = new HashMap<>();
    Set<Class<?>> primitiveArrayClasses = new HashSet<Class<?>>();

    public NullableEmbeddedCleanerImpl() {
        fillPredicates();
        fillCollectionMap();
        fillPrimitiveArrayClasses();
    }

    /**
     * B C D F I J S Z
     */
    private void fillPrimitiveArrayClasses() {
        try {
            primitiveArrayClasses.addAll(Arrays.asList(Class.forName("[B"), Class.forName("[B"), Class.forName("[C"),
                    Class.forName("[D"), Class.forName("[F"), Class.forName("[I"), Class.forName("[J"), Class.forName("[S"),
                    Class.forName("[Z")));
        } catch (ClassNotFoundException e) {
            LOGGER.error("Class not found", e);
        }
    }

    @SuppressWarnings("unchecked")
    private void fillCollectionMap() { // misses Lists, Maps, ...
        collection(Set.class, s -> {
            final Set<Object> toRemove = new HashSet<>();
            for (Object i : s) {
                try {
                    if (clean(i)) {
                        toRemove.add(i);
                    }
                } catch (Exception e) {
                    LOGGER.warn("Error cleaning embeddable {} : {}", e, i);
                }
            }
            s.removeAll(toRemove);
            return s.isEmpty();
        });
    }

    @Override
    public final void embeddables(Object... arg) {
        for (Object i : arg) {
            try {
                clean(i);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                LOGGER.warn("Error cleaning embeddable {} : {}", e, i);
            }
        }
    }

    @Override
    public final boolean clean(Object arg) throws IllegalArgumentException, IllegalAccessException {
        if (arg == null) {
            return true;
        }
        boolean cleanThis = true;
        Vector<Field> fields = new Vector<>();
        for (Class<?> clazz = arg.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        }
        for (Field field : fields) {
            if (!fieldLoop(field, arg)) {
                cleanThis = false;
            }
        }
        return cleanThis;
    }

    private boolean fieldLoop(Field field, Object arg) throws IllegalArgumentException, IllegalAccessException {
        if (Modifier.isStatic(field.getModifiers())) { // skip static fields
            return true;
        }
        field.setAccessible(true);
        Object fieldValue = field.get(arg);
        if (fieldValue == null) {
            return true;
        }
        Class<?> fieldsClass = field.getType();
        if (fieldsClass.isPrimitive() || fieldsClass.isEnum()) {
            return false; // can not clean primitives nor enums
        }
        if (fieldsClass.isArray()) {
            if (primitiveArrayClasses.contains(fieldsClass)) {
                return false; // ignore primitive arrays
            } else {
                throw new UnsupportedOperationException("Do something useful here"); // object
                                                                                                            // arrays
            }
        }
        for (Class<?> clazz : collectionMap.keySet()) {
            if (clazz.isAssignableFrom(fieldsClass)) {
                boolean emptyCollection = collectionMap.get(clazz).test(fieldValue);
                if (!emptyCollection) {
                    return false;
                } else {
                    field.set(arg, null);
                }
                return true;
            }
        }
        // test primitives. just classes, no interfaces >>
        for (Class<?> fieldClass = fieldsClass; fieldClass != null; fieldClass = fieldClass.getSuperclass()) {
            if (classFilterForNullables.containsKey(fieldClass)) {
                Predicate<Object> handle = classFilterForNullables.get(fieldClass);
                if (handle.test(fieldValue)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        if (clean(field.get(arg))) { // decent to contained objects
            field.set(arg, null);
        } else {// non clean-able child exists
            return false;
        }
        return true;
    }

    private void fillPredicates() {
        nullableFilters(String.class, Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class,
                Float.class, Double.class, Void.class, LocalDateTime.class, LocalDate.class, LocalTime.class,
                OffsetDateTime.class, OffsetTime.class);
        classFilterForNullables.put(NullableEmbeddedCleanerImpl.class, n -> true); // always
                                                                                                            // filter
    }

    private void nullableFilters(Class<?>... cs) {
        for (Class<?> c : cs) {
            classFilterForNullables.put(c, o -> false);
        }
    }

    @SuppressWarnings("unchecked")
    final private <T> void collection(Class<T> c, Predicate<T> fun) {
        collectionMap.put((Class<?>) c, ((Predicate<Object>) fun));
    }
}
公共类NullableEmbeddedCleanerImpl实现NullableEmbeddedCleaner{
私有最终静态记录器Logger=LoggerFactory.getLogger(NullableEmbeddedCleaner.class);
Map,Predicate>collectionMap=newhashmap();
Set>();
公共NullEmbeddedCleanerImpl(){
填充谓词();
fillCollectionMap();
fillPrimitiveArrayClasses();
}
/**
*B C D F I J S Z
*/
private void fillPrimitiveArrayClasses(){
试一试{
primitiveArrayClasses.addAll(数组.asList(Class.forName(“[B”)、Class.forName(“[B”)、Class.forName(“[C”),
类别名称(“[D”)、类别名称(“[F”)、类别名称(“[I”)、类别名称(“[J”)、类别名称(“[S”),
类别名称(“[Z”);
}catch(classnotfounde异常){
记录器错误(“未找到类”,e);
}
}
@抑制警告(“未选中”)
私有void fillCollectionMap(){//未命中列表、映射。。。
集合(集合类,s->{
final Set toRemove=新HashSet();
用于(对象i:s){
试一试{
如果(清洁(i)){
删除。添加(i);
}
}捕获(例外e){
warn(“清除可嵌入{}:{}的错误”,e,i);
}
}
s、 removeAll(toRemove);
返回s.isEmpty();
});
}
@凌驾
公共最终无效嵌入(对象…arg){
用于(对象i:arg){
试一试{
清洁(i);
}捕获(IllegalArgumentException | IllegalAccessException e){
warn(“清除可嵌入{}:{}的错误”,e,i);
}
}
}
@凌驾
公共最终布尔清除(对象arg)抛出IllegalArgumentException、IllegalAccessException{
如果(arg==null){
返回true;
}
布尔值:该值为真;
向量场=新向量();
对于(类clazz=arg.getClass();clazz!=null;clazz=clazz.getSuperclass()){
addAll(Arrays.asList(clazz.getDeclaredFields());
}
用于(字段:字段){
如果(!fieldLoop(字段,参数)){
这个=假;
}
}
把这个还给我;
}
私有布尔fieldLoop(字段,对象参数)抛出IllegalArgumentException,IllegalAccessException{
if(Modifier.isStatic(field.getModifiers()){//跳过静态字段
返回true;
}
字段。setAccessible(true);
对象字段值=field.get(arg);
如果(fieldValue==null){
返回true;
}
类fieldsClass=field.getType();
if(fieldsClass.isPrimitive()| | fieldsClass.isEnum()){
返回false;//无法清除基元或枚举
}
if(fieldsClass.isArray()){
if(PrimitiveArrayClass.contains(fieldsClass)){
返回false;//忽略基元数组
}否则{
抛出新的UnsupportedOperationException(“在这里做一些有用的事情”);//对象
//阵列
}
}
for(类clazz:collectionMap.keySet()){
if(类别isAssignableFrom(fieldsClass)){
布尔值emptyCollection=collectionMap.get(clazz.test)(fieldValue);
如果(!emptyCollection){
返回false;
}否则{
field.set(arg,null);
}
返回true;
}
}
//测试原语。只有类,没有接口>>
for(类fieldClass=fieldsClass;fieldClass!=null;fieldClass=fieldClass.getSuperclass()){
if(classFilterForNullables.containsKey(fieldClass)){
谓词句柄=classFilterForNullables.get(fieldClass);
if(句柄测试(字段值)){
返回true;
}否则{
返回false;
}
}
}
if(clean(field.get(arg)){//delegate到包含的对象
field.set(arg,null);
}else{//存在不可清除的子项
返回false;
}
返回true;
}
私有void fillPredicates(){
nullableFilters(String.class、Boolean.class、Character.class、Byte.class、Short.class、Integer.class、Long.class、,
Float.class、Double.class、Void.class、LocalDateTime.class、LocalDate.class、LocalTime.class、,
OffsetDateTime.class、OffsetTime.class);
classFilterForNullables.put(nullableMbeddedCleanerImpl.class,n->true);//始终
//滤器
}
私有void nullableFilters(类…cs){
对于(c类: