2011-08-28 28 views
15

क्या जेपीए का उपयोग कर ईमेल पते जैसे अपरिवर्तनीय मूल्य वस्तुओं को मानचित्र करने का कोई तरीका है?अपरिवर्तनीय मूल्य वस्तुएं और जेपीए

@Immutable 
@Embeddable 
public final class EmailAddress { 
    private final String value; 

    public EmailAddress(String value) { 
     this.value = value; 
    } 

    public String getValue() { 
     return value; 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 
     EmailAddress that = (EmailAddress) o; 
     return value.equals(that.value); 
    } 

    @Override 
    public int hashCode() { 
     return value.hashCode(); 
    } 
} 

अब मैं अपवाद इकाई पर बचाने

org.hibernate.InstantiationException: No default constructor for entity: com.domain.EmailAddress 
    org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:107) 
    org.hibernate.tuple.component.AbstractComponentTuplizer.instantiate(AbstractComponentTuplizer.java:102) 
    org.hibernate.type.ComponentType.instantiate(ComponentType.java:515) 
    org.hibernate.type.ComponentType.deepCopy(ComponentType.java:434) 
    org.hibernate.type.TypeHelper.deepCopy(TypeHelper.java:68) 
    org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:302) 
    org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203) 
    org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129) 
    org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69) 
    org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179) 
    org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) 
    org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) 
    org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808) 
    org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782) 
    org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786) 
    org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    java.lang.reflect.Method.invoke(Method.java:597) 
    org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
    $Proxy25.persist(Unknown Source) 
    org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:360) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    java.lang.reflect.Method.invoke(Method.java:597) 
    org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:368) 
    org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:349) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    $Proxy26.save(Unknown Source) 
    com.controller.UserController.create(UserController.java:64) 

मैं अंतिम फ़ील्ड का उपयोग और जेपीए कार्यान्वयन के रूप में हाइबरनेट चाहते।

उत्तर

13

आप जीत गए ' मानक जेपीए एनोटेशन और एक एम्बेड करने योग्य ऑब्जेक्ट का उपयोग करने में सक्षम नहीं हो सकता है, क्योंकि ऑब्जेक्ट को डिफॉल्ट कन्स्ट्रक्टर का उपयोग करके और प्रतिबिंब के माध्यम से मान सेट करना होगा।

हालांकि आप एक हाइबरनेट कस्टम प्रकार का उपयोग कर सकते हैं। this part of the Hibernate reference documentation पढ़ें, जहां एक उदाहरण Money प्रकार है, जिसे तर्क के साथ एक कन्स्ट्रक्टर का उपयोग करके तत्काल किया जाता है, और इस प्रकार अपरिवर्तनीय हो सकता है।

+0

बहुत बहुत धन्यवाद। यह पूरी तरह से अच्छी तरह से काम करता है। –

3

जेपीए प्रतिबिंब के माध्यम से वस्तुओं को बनाने में सक्षम होने के लिए, आपके पास एक डिफ़ॉल्ट कन्स्ट्रक्टर होना चाहिए, लेकिन इसे सार्वजनिक नहीं होना चाहिए। मैं अपने खेतों को अंतिम रखना भी पसंद करता हूं, लेकिन यह प्रतिबिंब के लिए बहुत ही सीमित हो सकता है - आपको कोशिश करनी होगी।

मैं अंतिम क्षेत्र संशोधक छोड़ने और एक छोटी टिप्पणी के साथ एक निजी डिफ़ॉल्ट निर्माता को जोड़ने (ताकि आप अभी भी जानते हो क्यों नहीं-op निर्माता वहाँ अगले सप्ताह है कि) का सुझाव चाहते हैं:

public final class EmailAddress { 
    private String value; // no final modifier 

    private EmailAddress() { 
     // for JPA 
    } 

    public EmailAddress(String value) { 
     this.value = value; 
    } 
... 
} 
+0

धन्यवाद प्राप्त कर सकते हैं। लेकिन मुझे उम्मीद है कि बेहतर होगा) –

+0

एक त्वरित परीक्षण मैंने मुझे निजी अंतिम फ़ील्ड को प्रतिबिंब के माध्यम से सेट करने दिया - ताकि आपके पास 'निजी अंतिम स्ट्रिंग मान' हो और डिफ़ॉल्ट कन्स्ट्रक्टर में 'this.value = null' - - लेकिन हाइबरनेट डॉक्स प्रॉक्सी/आलसी लोडिंग को सक्षम करने के लिए अंतिम संशोधक (कक्षा के लिए भी) पर वापस रखने का सुझाव देते हैं: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/persistentent -classes.html # persistent-classes-pojo-final –

+0

मुझे लगता है कि यह अच्छा त्वरित समाधान होगा। लेकिन मैं ईई विकास के लिए स्पष्ट बांधने की मशीन पसंद करेंगे। –

7

संभवत: सबसे आसान समाधान जो 3.5 पुराने हाइबरनेट जैसे छोटे पुराने संस्करणों के साथ काम करता है, है org.hibernate.usertype.UserType को लागू करना है। इसमें काफी कुछ तरीकों है, लेकिन अपरिवर्तनीय प्रकार के लिए आप आम सुपर क्लास करने के लिए उनमें से ज्यादातर निकाल सकते हैं:

package com.acme; 

import java.io.Serializable; 

import org.hibernate.usertype.UserType; 

public abstract class AbstractImmutableType 
    implements UserType { 

public AbstractImmutableType() { 
    super(); 
} 

public boolean isMutable() { 
    return false; 
} 

public Serializable disassemble(Object value) { 
    return (Serializable) value; 
} 

public Object assemble(Serializable cached, Object owner) { 
    return cached; 
} 

public Object deepCopy(Object value) { 
    return value; 
} 

public Object replace(Object original, Object target, 
    Object owner) { 
    return original; 
} 

public boolean equals(Object x, Object y) { 
    if (x != null && y != null) { 
    return x.equals(y); 
    } 
    // Two nulls are equal as well 
    return x == null && y == null; 
} 

public int hashCode(Object x) { 
    if (x != null) { 
    return x.hashCode(); 
    } 
    return 0; 
} 
} 

और तुम इस तरह इसका इस्तेमाल कर सकते हैं:

package com.acme; 

import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Types; 

public class CurrencyType extends AbstractImmutableType { 

public static final String TYPE = "com.acme.CurrencyType"; 

private static final int[] SQL_TYPES = { 
    Types.VARCHAR 
}; 

public CurrencyType() { 
    super(); 
} 

public Object nullSafeGet(ResultSet rs, String[] names, 
    Object owner) throws SQLException { 
    String value = rs.getString(names[0]); 
    if (rs.wasNull()) { 
    return null; 
    } 
    return Currency.valueOf(value); 
} 

public void nullSafeSet(PreparedStatement st, Object value, 
    int index) throws SQLException { 
    if (value != null) { 
    st.setString(index, ((Currency)value).getCode()); 
    } else { 
    st.setNull(index, SQL_TYPES[0]); 
    } 
} 

public Class<?> returnedClass() { 
    return Currency.class; 
} 

public int[] sqlTypes() { 
    return SQL_TYPES; 
} 
} 

लंबे समय तक इस कोड के लिए विवरण आप here

+0

धन्यवाद। मैं देख लूंगा –

संबंधित मुद्दे