मुझे लगता है कि मेरे पास आपके लिए समाधान है। आप जो रुचि रखते हैं वह एक कंपोजिट यूज़र टाइप है।
एक उदाहरण के रूप में एक इंटएड्रेस संयुक्त उपयोगकर्ता प्रकार का उपयोग करने के लिए मैंने हाल ही में एक 128 बिट आईपीवी 6 पता/IPv4Address ऑब्जेक्ट को उपयोगकर्ता खाता इकाई के अंदर दो 64 बिट लंबी गुणों को मैप करने के लिए लिखा है।
signupIp: InetAddress दो कॉलम (कोई स्तंभ संख्या सीमा या एक जैसे नहीं है) का उपयोग करने की दिशा में मैप किया गया है:
@Columns(columns = {@Column(name = "ip_low", nullable = true), @Column(name = "ip_high", nullable = true)})
private InetAddress signupIp;
और कार्यान्वयन के दिलचस्प हिस्सा इस तरह दिखता है:
public class InetAddressUserType implements CompositeUserType {
@Override
public String[] getPropertyNames() {
return new String [] {"ipLow", "ipHigh"};
}
@Override
public Type[] getPropertyTypes() {
return new Type [] { LongType.INSTANCE, LongType.INSTANCE};
}
@Override
public Object getPropertyValue(Object component, int property) throws HibernateException {
if(component != null)
return toLong((InetAddress)component)[property];
else
return null;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
if(value != null) {
long [] longs = toLong((InetAddress)value);
st.setLong(index, longs[0]);
st.setLong(index + 1, longs[1]);
}
else {
st.setNull(index, LongType.INSTANCE.sqlType());
st.setNull(index + 1, LongType.INSTANCE.sqlType());
}
}
@Override
public void setPropertyValue(Object component, int property, Object value)
throws HibernateException {
throw new RuntimeException("This object is immutable");
}
@Override
public Class<?> returnedClass() {
return InetAddress.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return x != null ? x.equals(y) : null == y;
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Long ipLow = rs.getLong(names[0]);
if(!rs.wasNull()) {
Long ipHigh = rs.getLong(names[1]);
try {
return fromLong(new long [] {ipLow, ipHigh});
} catch (UnknownHostException e) {
throw new HibernateException("Failed to get InetAddress: ip = " + ipHigh + " + " + ipLow, e);
}
}
else
return null;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
if(value != null)
try {
return InetAddress.getByAddress(((InetAddress)value).getAddress());
} catch (UnknownHostException e) {
throw new RuntimeException("Impossible Exception: " + e.getMessage(), e);
}
else
return null;
}
@Override
public boolean isMutable() {
return false;
}
...
}
ध्यान दें कि आईपीएलओ और आईपीएचई के मूल्यों के आधार पर मैं लचीला रूप से Inet4Address और Inet6Address उदाहरणों के बीच स्विच करता हूं। समग्र को अपरिवर्तनीय के रूप में चिह्नित किया जाता है और आपको हाइबरनेट स्रोत कोड (समग्र उपयोगकर्ता प्रकारों में निर्मित) में प्रलेखन और उदाहरणों की जांच करने की आवश्यकता होती है।
इसी तरह आप अपनी सार्थक बिट गुणों को मानचित्र बना सकते हैं। आप अपने EnumType को एक एकल Restriction.eq refering का उपयोग करके उन बिट्स से पूछ सकते हैं। आप गुण वस्तु की जांच करने के लिए बराबर विधि का उपयोग कर सकते हैं। और यदि आपको एक विशेष मैप किए गए बिट को संदर्भित करने की आवश्यकता है तो आप ipLow प्रॉपर्टी/कॉलम को संदर्भित करने के लिए साइनअप Ip.ipLow में डॉट नोटेशन का उपयोग कर सकते हैं।
मुझे लगता है कि यह वही है जो आप खोज रहे हैं।
अद्यतन:
अंत इसे नीचे फोड़े अपने गुणों का सही क्रम को परिभाषित करने के। अपने StatusCompositeType कक्षा में
//immutable for simplicity
class Status {
private final boolean editable;
private final boolean needsReview;
private final boolean active;
//... constructor + isEditable etc..
}
: हाइबरनेट हमेशा एक संपत्ति का उपयोग करने के पूर्णांक सूचक मान का उपयोग करेगा
public String[] getPropertyNames() {
return new String [] {"editable", "needsReview", "active"};
}
public Type[] getPropertyTypes() {
return new Type [] { BooleanType.INSTANCE, LongType.INSTANCE};
}
public Object getPropertyValue(Object component, int property) throws HibernateException {
if(component != null) {
Status status = (Status)component;
switch(property) {
case 1: return status.isEditable();
case 2: return status.isReviewNeeded();
case 3: return status.isActive();
default: throw new IllegalArgumentException();
}
}
else
return null; //all columns can be set to null if you allow a entity to have a null status.
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
if(value != null) {
Status status = (Status)value;
st.setBoolean(index, status.isEditable());
st.setBoolean(index + 1, status.isReviewNeeded());
st.setBoolean(index + 2, status.isActive());
}
else {
st.setNull(index, BooleanType.INSTANCE.sqlType());
st.setNull(index + 1, BooleanType.INSTANCE.sqlType());
st.setNull(index + 2, BooleanType.INSTANCE.sqlType());
}
}
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Boolean isEditable = rs.getBoolean(names[0]);
if(!rs.wasNull()) {
Boolean isReviewNeeded = rs.getBoolean(names[1]);
Boolean isActive = rs.getBoolean(names[2]);
return new Status(isEditable, isReviewNeeded, isActive);
}
else
return null;
}
बाकी सीधे आगे है।उपयोगकर्ता प्रकार के लिए बराबर और हैशकोड को लागू करना याद रखें और अपना सत्र बनाने से पहले कॉन्फ़िगरेशन में टाइप जोड़ें। फैक्टरी।
एक बार जब आप सब कुछ जगह में आप एक मापदंड खोज बना सकते हैं और उपयोग कर सकते हैं:
//search for any elements that have a status of editable, no reviewNeeded and is not active (true false false).
criteria.add(Restrictions.eq("status", new Status(true, false, false));
अब आप अपने listEntities विधि बन सकते हैं या तो: listEntities(Status status)
या listEntities(boolean editable, boolean reviewNeeded, boolean isActive)
।
यदि आपको अतिरिक्त जानकारी की आवश्यकता है तो बस कंपोजिट टाइप और बेसिक टाइप टाइप कार्यान्वयन की जांच करें हाइबरनेट अपने स्रोत स्रोत (कंपोजिट टाइप और बेसिक टाइप के कार्यान्वयनकर्ताओं के लिए देखें) के भीतर प्रदान करता है। उनको समझना बहुत मदद करता है और हाइबरनेट के इस मध्यवर्ती स्तर के ज्ञान को सीखने में मदद करता है।
मुझे इसके लिए संबंध बनाने की आवश्यकता पर विचार नहीं है। मैं सिर्फ यह जांचूंगा कि क्या मैं 'EnumUserType' के साथ कुछ हासिल कर सकता हूं। धन्यवाद! –
संभावित रूप से आप इसे 'EnumUserType' के साथ प्राप्त कर सकते हैं लेकिन हर बार जब आप एक नया ध्वज जोड़ते हैं तो आपको एक नया बूलियन जोड़ने के लिए डेटाबेस को बदलना होगा, उपयोगकर्ता प्रकार में मैपिंग और अपनी गणना में एक नया मान जोड़ना होगा जबकि अन्य दृष्टिकोण डेटाबेस को बिल्कुल बदलना नहीं होगा, बस नई गणनाएं जोड़ें –
यह वास्तव में महत्वपूर्ण है कि यह इंटरफेस को बनाए रखता है। एक बार यह हासिल करने के बाद मैं केवल हाइबरनेट को बताना चाहता हूं कि enum बुलियन मूल्यों से मेल खाता है। मैं बस 'सेट' में कुछ नए एनम वैल्यू को सहेजने में सक्षम होना चाहता हूं और संबंधित बुलियन वैल्यू को 1 पर सेट करना चाहता हूं। नए मान जोड़ने के लिए मैपिंग को बदलना कोई समस्या नहीं है, यह कुछ सामान्य नहीं होगा। –