كيفية تعيين خاصية غير محددة إلى قيمة دون الحصول على NullPointerException في Dozer

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

  •  05-07-2019
  •  | 
  •  

سؤال

باستخدام Dozer لتعيين كائنين، لدي:

/**
/* This first class uses the GXT (ExtJS) framework
**/
Class1 extends BaseModelData
{
    public int getId()
    {
        return (Integer)get("id");
    }

    public void setId(int id)
    {
        set("id", id);
    }

    // more properties
}

Class2
{
    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }

    // more properties
}

إذا لم أقم بتعيين المعرف في الفئة الأولى (عن طريق استدعاء class1.setId()) فستكون النتيجة NullPointerException من Dozer.أتفهم أن هذا صحيح لأن get("id") سيكون فارغًا.

يمكنني بالطبع حل هذه المشكلة عن طريق التحقق من القيمة الخالية وإرجاع -1 أو 0 أو أيًا كان.

المشكلة هي أن هذا يصبح خطأ وقت التشغيل بدلاً من خطأ وقت الترجمة.أفضّل حل هذه المشكلة بشكل صحيح.

والآن قرأت في وثائق البلدوزر التي يمكنك جعلها تتخطى القيمة الخالية عن طريق القيام بـmap-null="false", ، لكن لم أتمكن من تنفيذ هذا...

أي اقتراحات؟

هل كانت مفيدة؟

المحلول

أعتقد أن المشكلة ليست في البلدوزر، ولكن في عملية إلغاء العلبة التلقائية المخفية في جهاز getter الخاص بك:

   public int getId()
{
    return (Integer)get("id");
}

(Integer)get("id") يتم تحويله ضمنيًا إلى int لأن نوع الإرجاع لطريقتك هو "int".

وهذا سوف ينجح في معظم الحالات ...باستثناء عندما تكون النتيجة فارغة، وفي هذه الحالة تحصل على NullPointerException لأن int قد لا يكون فارغًا أبدًا.

يؤدي هذا إلى NullPointerExceptions المخفية...مزيد من المعلومات هنا: http://www.theserverside.com/blogs/thread.tss?thread_id=41731

لحل هذه المشكلة، لديك خيارات متعددة:

  • إذا كان Class1 وClass2 يحتويان في الواقع على معرف فارغ، فأنت تريد تعديل الحروف/المحددات الخاصة بك للحصول على/تعيين أعداد صحيحة بدلاً من الأعداد الصحيحة البدائية.

  • إذا كان يجب ألا يحتوي كل من Class1 وClass2 مطلقًا على معرف فارغ، وكنت تعتبر هذا فئة ثابتة، فيمكنك الاحتفاظ بنوع int البدائي في getter/setter وإما:

    • تأكد من أن get("id") لن يكون فارغًا أبدًا، عن طريق تهيئته لبعض القيمة المحددة (مثل 0) في المُنشئ)، والتأكد من أنه لا يوجد شيء يمكن تعيينه على قيمة فارغة.
    • أو قرر أن getId() سيُرجع قيمة افتراضية إذا كانت فارغة، وإضافة علامة اختيار فارغة في المُحضر كما قلت.
  • إذا كان من الممكن أن يكون لدى Class1 معرفًا فارغًا، ولكن قد لا يكون لدى Class2 معرفًا فارغًا، فيجب أن يكون لديك حروف ومحددات Class1 تستخدم نوعًا صحيحًا بدلاً من int أولي، ويجب عليك إنشاء بلدوزر CustomConverter يقوم بإرجاع قيمة افتراضية عندما يكون الحقل المصدر خاليًا.

يعتبر


[عدل] إليك رمز الاختبار الذي يوضح أن البلدوزر يتجاهل تعيين القيم الخالية عندما يطلب منه:

src/com/test/dozer/Class1.java :

package com.test.dozer;

import com.extjs.gxt.ui.client.data.BaseModelData;

public class Class1 extends BaseModelData {

    // Notice the return type here: "Integer" and *not* int
    // Returning int throws a NullPointerException when get("id") is null!
    public Integer getId() {
        return (Integer) get("id");
    }

    public void setId(Integer id) {
        set("id", id);
    }

}

src/com/test/dozer/Class2.java :

package com.test.dozer;

public class Class2 {

    private int id;

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

src/dozerMappingFile.xml :

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd">

  <configuration>
    <stop-on-errors>true</stop-on-errors>
    <date-format>MM/dd/yyyy HH:mm</date-format><!-- default dateformat will apply to all class maps unless the class mapping explicitly overrides it -->
    <wildcard>true</wildcard><!-- default wildcard policy that will apply to all class maps unless the class mapping explicitly overrides it -->
  </configuration>

  <mapping map-null="false">
    <class-a>com.test.dozer.Class1</class-a>
    <class-b>com.test.dozer.Class2</class-b>
  </mapping>

</mappings>

src/com/test/dozer/DozerTest.java :

package com.test.dozer;

import java.util.Arrays;

import junit.framework.Assert;

import org.dozer.DozerBeanMapper;
import org.junit.Before;
import org.junit.Test;

public class DozerTest {

    private DozerBeanMapper mapper;

    @Before
    public void setUp() {
        mapper = new DozerBeanMapper(Arrays.asList("dozerMappingFile.xml"));
    }

    /**
     * Verifies that class1's id is mapped into class2's id when not null.
     */
    @Test
    public void testMappingWhenIdNotNull() {
        Class1 class1 = new Class1();
        class1.setId(1);
        Class2 class2 = new Class2();
        class2.setId(2);

        mapper.map(class1, class2);

        Assert.assertEquals(1, class2.getId());
    }

    /**
     * Verifies that class2's id is not set to null when class1's id is null.
     */
    @Test
    public void testMappingWhenIdIsNull() {
        Class1 class1 = new Class1();
        Class2 class2 = new Class2();
        class2.setId(2);

        mapper.map(class1, class2);

        Assert.assertEquals(2, class2.getId());
    }

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