كيفية استخدام التعداد مع JPA كعضو بيانات في الكيان المستمر؟

StackOverflow https://stackoverflow.com/questions/1979176

  •  22-09-2019
  •  | 
  •  

سؤال

يرجى أفضل الممارسات و "كيفية" لاستخدام التعداد مع JPA كعضو بيانات في الكيان المستمر. ما هو أفضل الممارسات؟ أريد أن أستمر "C" ، "O" من التعداد. (الرموز). إذا لم يكن هذا هو النهج الصحيح من فضلك اقترح.

تعداد الدفء هو -

public enum Status{
CLOSED ("C")
OPEN ("O")
private final int value;
private Status(final int pValue){
this.value = pValue;
}

public int value(){
 return this.value;
}
هل كانت مفيدة؟

المحلول

الحل المتوقع:تعداد الدفء:

public enum Status {
    CLOSED(1), NEW(2), RUNNING(3), OPEN(4), ADDED(5), SUCEESS(-1), DONE(0);
        private int code;
        private Status(int code) {
        this.code = code;
    }
        public int getCode() {
        return code;
    }
        public void setCode(int code) {
        this.code = code;
    }
        public static Status valueOf(int i){
        for (Status s : values()){
            if (s.code == i){
                return s;
            }
        }
        throw new IllegalArgumentException("No matching constant for " + i);
    }

}

تعريف الكيان:

@Entity
@NamedQuery(name="Process.findAll", query="select p from Process p ")
public class Process {

    @Id
    private long id;
    private String name;

    @Transient
    private transient Status status; //actual enum; not stored in db
        @Column(name="STATUS")  
    private int statusCode; // enum code gets stored in db

    @PrePersist
    void populateDBFields(){
        statusCode = status.getCode();
    }

    @PostLoad
    void populateTransientFields(){
        status = Status.valueOf(statusCode);
    }
    public long getId() {
        return id;
    }
        public void setId(long id) {
        this.id = id;
    }
        public String getName() {
        return name;
    }
        public void setName(String name) {
        this.name = name;
    }
        public Status getStatus() {
        return status;
    }
        public void setStatus(Status status) {
        this.status = status;
    }
}

نصائح أخرى

نحن نستمر في التعداد كقواسل. يستخدم @Enumerated(EnumType.STRING) لاستخدام تمثيل السلسلة (بدلاً من رمز التعداد التلقائي). هذا يجعل بياناتك في DB أكثر قابلية للقراءة.

إذا كنت بحاجة حقًا إلى تعيين التعدادات إلى رموز خاصة (الرمز القديم وما شابه) ، فستحتاج إلى رسم خرائط مخصص. أولا فئة أساسية تقوم بتعيين تعداد DB والعودة:

import java.io.Serializable;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;


public abstract class CustomEnumType implements UserType
{
    public Object deepCopy (Object value) throws HibernateException
    {
        return value;
    }

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

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

    public boolean equals (Object x, Object y) throws HibernateException
    {
        // Correct for Enums
        return x == y;
    }

    public int hashCode (Object x) throws HibernateException
    {
        return x.hashCode ();
    }

    public boolean isMutable ()
    {
        return false;
    }

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

    public int[] sqlTypes ()
    {
        return new int[]{ Hibernate.STRING.sqlType() };
    }

}

الآن امتداد يستخدم DBenum لتعيين القيم لتعدادك إلى DB والعودة:

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

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.apache.log4j.Logger;

public abstract class DBEnumType extends CustomEnumType
{
    private final static Logger log = Logger.getLogger(DBEnumType.class);
    private static final boolean IS_VALUE_TRACING_ENABLED = log.isTraceEnabled();

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

        return toEnum (value);
    }

    public abstract Object toEnum (String value);

    public void nullSafeSet (PreparedStatement st, Object value, int index)
            throws HibernateException, SQLException
    {
        if (value == null)
            st.setNull (index, Hibernate.STRING.sqlType ());
        else
        {
            DBEnum dbEnum = (DBEnum)value;
            value = dbEnum.getDBCode();
            st.setString (index, dbEnum.getDBCode());
        }

        if (IS_VALUE_TRACING_ENABLED)
        {
            log.trace (getClass().getName()+" "+value);
        }
    }
}

الواجهة:

public interface DBEnum
{
    public String getDBCode ();
}

أخيرًا ، يجب أن تمتد DBEnumType لكل نوع تعداد تريد تعيينه:

public class DBEnumCardType extends DBEnumType
{
    public Class returnedClass ()
    {
        return Status.class;
    }

    public Object toEnum (String value)
    {
        return Status.fromDBCode (value);
    }

}

في Status, ، يجب عليك تنفيذ الطريقة الثابتة التي تقوم بتخطيط رموز DB إلى التعداد:

    private final static Map<String, Status> dbCode2Enum = new HashMap<String, Status> ();
    static {
        for (Status enm: Status.values ())
        {
            String key = enm.getDBCode ();
            if (dbCode2Enum.containsKey (key))
                throw new ShouldNotHappenException ("Duplicate key "+key+" in "+enm.getClass ());
            dbCode2Enum.put (key, enm);
        }
    }

    private String dbCode;

    private Status (String dbCode)
    {
        this.dbCode = dbCode;
    }

    public String getDBCode ()
    {
        return dbCode;
    }

    public static Status fromDBCode (String dbCode)
    {
        if (dbCode == null)
            return null;

        Status result = dbCode2Enum.get (dbCode);
        if (result == null)
            throw new ShouldNotHappenException ("Can't find key "+dbCode+" in "+Status.class);

        return result;
    }

أخيرًا ، يجب عليك استخدام التعليق التوضيحي @org.hibernate.annotations.Type() لإخبار Hibernate لاستخدام رسم الخرائط المخصصة.

الخلاصة: لا تستخدم الرموز المخصصة. إنهم يولدون الكثير من رمز لوحة الغلايات الغبي الذي لا يمكنك عوامله.

تعتبر التعدادات افتراضيًا تدعمها JPA ، لكن المشكلة هي أنها تستخدم أوامر القيم افتراضيًا لا يمكنك التحكم فيها. لحل هذا ، يمكنك استخدام القليل من المنطق على مستقلين getter الخاص بك.

@Column(name = "KIRSAL_METROPOL")
private String someEnum;
public YourEnum getSomeEnum() {
    return EnumUtils.getEnum(YourEnum.class, this.someEnum);
}

public void setSomeEnum(YourEnum someEnum) {
    this. someEnum = EnumUtils.getValue(someEnum);
}

يجب أن تقوم التعدادات بالتحويل ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top