6

Tôi có một đối tượng Java được lập bản đồ ngủ đông, JKL, có đầy đủ các trường có khả năng ngủ đông bình thường (như chuỗi và số nguyên).Ánh xạ một tùy chọn FunctionalJava <Type> với Hibernate

Tôi đã thêm trường được nhúng mới vào trường (nằm trong cùng một bảng - không phải bản đồ), asdf, là fj.data.Option<ASDF>. Tôi đã làm cho nó một tùy chọn để làm cho nó rõ ràng rằng lĩnh vực này có thể không thực sự chứa bất cứ điều gì (như trái ngược với việc phải xử lý null mỗi khi tôi truy cập nó).

Làm cách nào để thiết lập ánh xạ trong tệp JKL.hbm.xml của tôi? Tôi muốn hibernate tự động chuyển đổi một null trong cơ sở dữ liệu thành một số none của fj.data.Option<ASDF> khi nó truy lục đối tượng. Nó cũng sẽ chuyển đổi một thể hiện không rỗng của ASDF thành một số some của fj.data.Option<ASDF>. Có bất kỳ thủ thuật nào khác mà tôi phải làm không? Cảm ơn bạn.

Trả lời

12

Tôi khuyên bạn nên giới thiệu chức năng Option của FunctionalJava trong bộ tiếp cận (getter và setter), trong khi rời Hibernate để xử lý trường java đơn giản được phép là null.

Ví dụ, đối với một tùy chọn Integer lĩnh vực:

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

Bạn có thể ánh xạ một Hibernate lĩnh vực tư nhân trực tiếp:

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

Sau đó, bạn có thể giới thiệu Option ở ranh giới accessor:

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

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

Điều đó có phù hợp với nhu cầu của bạn không?

2

Bạn có thể sử dụng các loại ánh xạ tùy chỉnh của Hibernate. Tài liệu là here. Đây là một ví dụ tương tự của mapping Scala's Option đối với ánh xạ Hibernate.

Nói một cách đơn giản, bạn cần mở rộng giao diện org.hibernate.UserType. Bạn cũng có thể tạo một lớp cơ sở kiểu chung với một kiểu phụ kiểu JKL, tương tự như những gì bạn thấy trong ví dụ Scala.

0

Tôi nghĩ rằng sử dụng getter/setter là đơn giản, nhưng đây là một ví dụ về những gì tôi đã làm để làm cho nó hoạt:

(Nó hoạt động tốt cho số lượng và chuỗi, nhưng không phải cho ngày (lỗi với @Temporal chú thích)).

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; 
} 
} 
Các vấn đề liên quan