6

Mam obiekt Java mapowany w hibernacji, JKL, który jest pełen garstki normalnych mapowania hibernacji pól (jak ciągi i liczby całkowite).Mapowanie funkcjonalnej opcji Javy <Type> z Hibernate

Dodałem do niego nowe pole osadzone (które znajduje się w tej samej tabeli - nie odwzorowanie), asdf, które jest fj.data.Option<ASDF>. Stworzyłem opcję, aby wyjaśnić, że to pole może w rzeczywistości nie zawierać niczego (w przeciwieństwie do konieczności obsługiwania null za każdym razem, gdy uzyskuję do niego dostęp).

Jak skonfigurować mapowanie w moim pliku JKL.hbm.xml? Chciałbym hibernacji, aby automatycznie przekonwertować null w bazie danych na none z fj.data.Option<ASDF>, gdy pobierze obiekt. Powinien także przekonwertować niezerową instancję z ASDF na some z fj.data.Option<ASDF>. Czy jest jakaś inna sztuczka, którą muszę zrobić? Dziękuję Ci.

Odpowiedz

12

Proponowałbym wprowadzenie funkcji FunctionalJava w wersji Option w akcesoriach (program pobierający i ustawiający), pozostawiając Hibernate, aby obsłużyć proste pole java, które może być null.

Na przykład dla opcjonalnego Integer polu:

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

można zmapować hibernacji prywatne pole bezpośrednio:

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

Następnie można przedstawić Option na granicy akcesor:

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

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

Czy to działa dla twoich potrzeb?

2

Można używać niestandardowych typów odwzorowań Hibernate. Dokumentacja to here. Oto analogiczny przykład od mapping Scala's Option do mapowania hibernacji.

Po prostu trzeba rozszerzyć interfejs org.hibernate.UserType. Można również utworzyć podstawową klasę podstawową z podtypem JKL, podobną do tego, co widać w przykładzie Scala.

0

myślę użyciu getter/setter jest prostsza, ale tutaj jest przykład tego, co zrobiłem, aby to działało:

(To działa dobrze dla liczby i ciąg, ale nie na bieżąco (błąd z @Temporal adnotacji)).

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; 
} 
} 
Powiązane problemy