سؤال

أنا أستخدم Hibernate كموفر JPA الخاص بي حيث يتصل بقاعدة بيانات التقدم.عندما تستمر قيمة NaN، فإنها تسبب الكثير من المشكلات - فهي تمنع قراءة الصف في ظروف معينة.هل هناك طريقة للربط بثبات النوع المزدوج القياسي لتحويل NaN (وربما + و- اللانهاية) إلى قيمة مختلفة؟لا يهم إذا فقدت معلومات NaN أو اللانهاية، أريد فقط صفًا قابلاً للقراءة!

أعلم أنه يمكنني فعل شيء مثل هذا:

@Column(name = "doubleColumn")
public double getDoubleColumn() {
    return PersistedDouble.convert(doubleColumn);
}

لكنني قلق بشأن الصيانة حيث يجب إضافتها يدويًا لأي مضاعفات تم تعيينها لقاعدة البيانات.

نصائح أخرى

هل يمكن تعديل السبات نفسها. كل ما عليك القيام به هو تغيير DoubleType الصف.

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

وبعد هذه المناقشة, لدي شعور بأن السبات لا يوفر طريقة لتحويل NaN إلى شيء آخر.أعتقد أنه يجب عليك منع قيم NaN مبكرًا، حتى قبل كتابتها إلى متغيرات أعضاء الفول (مثل إضافة كود الحماية/التحويل إلى أدوات الضبط).

يحرر

أخشى أن أفضل حل غير سار هو استخدام كود الحماية، والأسوأ من ذلك، استخدام عمود إضافي على الطاولة، لتحديد ما إذا كانت القيمة رقمًا أم لا.ما سيؤدي بالتأكيد إلى تعقيد الاستعلام وإدراج العمليات.لكنك تحتاج إلى NaN في قاعدة البيانات ولا يمكنك محاربة برنامج التشغيل/قاعدة البيانات jdbc لتتصرف بشكل صحيح (وتقبل NaN كمدخلات صالحة لحقول NUMBER).

ولقد استخدمت حل نوع المستخدم في النهاية ولكن حل القضية صيانة مع وحدة الاختبار. الطبقة النوع هو كما يلي:

public class ParsedDoubleType extends DoubleType {
    private static final long serialVersionUID = 1L;

    @Override
    public void set(PreparedStatement st, Object value, int index) throws SQLException {
        Double doubleValue = (Double) value;
        if (doubleValue.isInfinite() || doubleValue.isNaN()) {
            Logger.getLogger(ParsedDoubleType.class).warn("Attempted to send a NaN or infinity value to the database " 
                + "- this is not supported.\nStatement=" + st + " valueIndex=" + index);
            doubleValue = Double.valueOf(0);
        }
        super.set(st, doubleValue, index);
    }
}

واختبار وحدة هو ما يقرب من (بعض التفاصيل إزالة الإيجاز):

Ejb3Configuration hibernateConfig = new Ejb3Configuration().configure("InMemoryDatabasePersistenceUnit", null);
for (Iterator<?> iterator = hibernateConfig.getClassMappings(); iterator.hasNext();) {
    PersistentClass clazz = (PersistentClass) iterator.next();
    Iterator<?> propertyIterator = clazz.getPropertyIterator();
    while (propertyIterator.hasNext()) {
        if (property.getType().equals(Hibernate.DOUBLE)) {
            Assert.fail("Raw double type found. Annotate with @Type(type = \"package.ParsedDoubleType\")\n" 
                + "Class " + clazz + " property " + property);
        }
    }
}

وكان لي بالضبط نفس المشكلة، وبتوجيه من هذه الحلول، وأنا على استعداد أيضا فئة النوع المخصص توسيع DoubleType. داخل تلك الفئة I تحويل القيم نان لاغية في وظيفة مجموعة والعكس صحيح بالنسبة للوظيفة الحصول عليها، منذ باطل هو موافق للأعمدة قاعدة البيانات الخاصة بي. أود أيضا أن تغير رسم الخرائط للأعمدة المحتملة نان إلى فئة نوع مخصص. عملت هذا الحل تماما لالسبات 3.3.2.

ومما يؤسف له، بعد الترقية السبات إلى 3.6.10، وتوقفت عن العمل. من أجل العمل على انجاحه مرة أخرى، واستبدال نوع مخصص من توسيع DoubleType لتنفيذ نوع المستخدم.

وينبغي أن يكون تطبيقات مهمة وظيفة نوع البيانات كما يلي:

private int[] types = { Types.DOUBLE };

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

@SuppressWarnings("rawtypes")
public Class returnedClass()
{
    return Double.class;
}

وهنا هي وظائف الحصول على وتعيين:

public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException
{
    Double value = rs.getDouble(names[0]);
    if (rs.wasNull())
        return Double.NaN;
    else
        return value;
}

public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException
{
    Double dbl = (Double) value;
    if ((dbl == null) || (Double.isNaN(dbl)))
        ps.setNull(index, Types.DOUBLE);
    else
        ps.setDouble(index, dbl);
}

وآسف ولكن انطلاقا من الأمثلة وسؤالك لديك فعلا مشاكل فهم جافا المثابرة. قاعدة بيانات الكيانات عبر حاصل على واضعي المدارة ذاتيا - هذه يمكن أن تفعل أي التحقق من صحة ترغب ان يكون لهم. إذا كنت حقا تعيين سمات بدونها، كنت في عداد المفقودين المفاهيم الأساسية للتنمية واستمرار وجوه المنحى - كيانات تدار بشكل خاص. بدا لي تحتاج إلى إعادة تصميم المشروع، وجود مشاكل مثل هذه هي علامة على يقين من عيوب في التصميم الأساسية ... مجرد إعطاء بعض النصائح هنا - وأن يكون الحل:

@Column(name="doubleColumn"}
private Double doubleColumn = Double.NaN  //yes, this is intentional. Verily.

public void setDouble(Double d)
{
    if(d.isNan || d.isInfinite()
    {
       //do something nice here
    }
    else
       this.doubleColumn = d;
}
public Double getDouble()
{
   return !this.doubleColumn.isNaN() && !this.doubleColumn.isInfinite() ? this.doubleColumn : new Double();
}

و.... لها بهذه السهولة.

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