Pergunta

Usando Dozer para mapear dois objetos, eu tenho:

/**
/* 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
}

Se eu não definir o Id na primeira classe (chamando class1.setId ()) o resultado é uma NullPointerException de Dozer. Eu entendo que isso é correto como get ( "id") seria nula.

I pode, naturalmente, resolver isso colocando em um cheque de null, e retornando -1 ou 0, ou o que quer.

O problema é que esta torna-se então um erro de execução, em vez de um erro de tempo de compilação. Eu prefiro muito mais para resolver isso corretamente.

Agora que eu li no documentação Dozer que você pode tê-lo pular nula fazendo mapa -null = "false" , mas eu não poderia chegar a este trabalho ...

Todas as sugestões?

Foi útil?

Solução

Eu acredito que o problema não está na lâmina, mas no escondido em seu getter-unboxing auto:

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

(Integer) get ( "id") está implicitamente lançado um int porque o tipo de retorno do seu método é "int".

Isto irá funcionar na maioria dos casos ... exceto quando o resultado é nulo, caso em que você começa um NullPointerException porque um int nunca pode ser nulo.

Isso resulta em NullPointerExceptions escondidos ... Mais informações aqui: http: / /www.theserverside.com/blogs/thread.tss?thread_id=41731

Para resolver isso, você tem várias opções:

  • Se Class1 e Class2 pode de fato conter uma id nulo, que pretende modificar seus getters / setters para obter / definir inteiros em vez de ints primitivos.

  • Se ambos Class1 e Class2 nunca deve conter uma id nulo, e se considera que este é um invariante de classe, você pode manter o tipo primitivo int no getter / setter e:

    • Certifique-se de obter ( "id") nunca será nula, inicializando-lo para algum valor específico (como 0) no construtor), e certificando-se de que nada pode defini-lo como nulo.
    • Ou decidir que getId () irá retornar um valor padrão se nulo, e adicionar um cheque nulo no getter como você disse.
  • Se Class1 pode ter um ID de null, mas Class2 não pode, você deve ter getters de Class1 e setters usar um tipo de Integer em vez de um int primitivo, e você deve criar que retorna um valor padrão a CustomConverter lâmina quando o campo de origem é nulo.

Saudações


[EDIT] Aqui está o código de teste que mostra que Dozer faz ignorar valores nulos de mapeamento quando solicitado a:

src / com / test / lâmina / 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 / lâmina / 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 / lâmina / 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());
    }

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top