6

我有一个休眠映射的 Java 对象,JKL它充满了一堆普通的休眠映射字段(如字符串和整数)。

我添加了一个新的嵌入字段(它位于同一个表中——不是映射)asdf,它是一个fj.data.Option<ASDF>. 我已将其作为一个选项,以明确该字段实际上可能不包含任何内容(而不是null每次访问时都必须处理)。

如何在我的JKL.hbm.xml文件中设置映射?我希望hibernate在它检索对象时自动将null数据库中的anone转换为a。fj.data.Option<ASDF>它还应该将一个非空实例转换为ASDF一个somefj.data.Option<ASDF>我还需要做什么其他的诡计吗?谢谢你。

4

3 回答 3

12

我建议Option在访问器(getter 和 setter)中引入 FunctionalJava,同时让 Hibernate 处理一个简单的 java 字段,该字段允许null.

例如,对于可选Integer字段:

// SQL
CREATE TABLE `JKL` (
    `JKL_ID` INTEGER PRIMARY KEY,
    `MY_FIELD` INTEGER DEFAULT NULL
)

您可以直接映射 Hibernate 私有字段:

// Java
@Column(nullable = true)
private Integer myField;

然后,您可以Option在访问器边界处引入:

// Java
public fj.data.Option<Integer> getMyField() {
    return fj.data.Option.fromNull(myField);
}

public void setMyField(fj.data.Option<Integer> value) {
    myField = value.toNull();
}

这对您的需求有用吗?

于 2012-05-15T16:34:45.887 回答
2

您可以使用 Hibernate 的自定义映射类型。文档在这里这是一个将 Scala 的 Option映射到 Hibernate 映射的类似示例。

简而言之,您需要扩展org.hibernate.UserType接口。您还可以创建具有JKL-typed 子类型的泛型类型基类,类似于您在 Scala 示例中看到的内容。

于 2012-05-15T17:29:23.627 回答
0

我认为使用getter/setter更简单,但这是我为使其工作所做的一个示例:

(它适用于数字和字符串,但不适用于日期(@Temporal注释错误))。

import com.cestpasdur.helpers.PredicateHelper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
import org.joda.time.DateTime;

import java.io.Serializable;
import java.sql.*;

public class OptionUserType implements UserType {


@Override
public int[] sqlTypes() {
    return new int[]{
            Types.NULL
    };
}

@Override
public Class returnedClass() {
    return Optional.class;
}

@Override
public boolean equals(Object o, Object o2) throws HibernateException {
    return ObjectUtils.equals(o, o2);

}

@Override
public int hashCode(Object o) throws HibernateException {
    assert (o != null);
    return o.hashCode();
}

@Override
public Optional<? extends Object> nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
    return Optional.fromNullable(rs.getObject(names[0]));
}

@VisibleForTesting
void handleDate(PreparedStatement st, Date value, int index) throws SQLException {
    st.setDate(index, value);
}

@VisibleForTesting
void handleNumber(PreparedStatement st, String stringValue, int index) throws SQLException {
    Double doubleValue = Double.valueOf(stringValue);
    st.setDouble(index, doubleValue);
}

@Override
public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {

    if (value != null) {
        if (value instanceof Optional) {
            Optional optionalValue = (Optional) value;
            if (optionalValue.isPresent()) {
                String stringValue = String.valueOf(optionalValue.get());


                if (StringUtils.isNotBlank(stringValue)) {

                    if (PredicateHelper.IS_DATE_PREDICATE.apply(stringValue)) {
                        handleDate(st, new Date(DateTime.parse(stringValue).getMillis()), index);
                    } else if (StringUtils.isNumeric(stringValue)) {
                        handleNumber(st, stringValue, index);
                    } else {
                        st.setString(index, optionalValue.get().toString());
                    }
                } else {
                    st.setString(index, null);
                }


            } else {
                System.out.println("else Some");
            }

        } else {
            //TODO replace with Preconditions guava
            throw new IllegalArgumentException(value + " is not implemented");

        }
    } else {
        st.setString(index, null);

    }


}

@Override
public Object deepCopy(Object o) throws HibernateException {
    return o;
}

@Override
public boolean isMutable() {
    return false;
}

@Override
public Serializable disassemble(Object o) throws HibernateException {
    return (Serializable) o;
}

@Override
public Object assemble(Serializable serializable, Object o) throws HibernateException {
    return serializable;
}

@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
    return original;
}
}
于 2013-05-11T13:18:59.930 回答