Estoy desarrollando una aplicación usando Hibernate, Spring y GWT en Java. He utilizado la ingeniería inversa en virtud de la Hibernación (JBoss Developer Studio se utiliza) para obtener POJOs y los archivos de configuración a partir de una base de datos MySQL. Es muy sencilla base de datos con sólo dos entidades: el País y de los Ciudadanos. Tienen OneToMany relación entre.

Aquí está el código:

aplicación de punto de entrada:

...

                    Country country = new Country();
                    country.setName("NameOfCountry"+i);
                    country.setPopulation(10000);

                    Citizen ctz = new Citizen();
                    ctz.setName("John");
                    ctz.setSurname("Smith");


                    ctz.setCountry(country);
                    country.getCitizens().add(ctz);

                    service.saveCitizen(ctz, new AsyncCallback<Boolean>(){

                        @Override
                        public void onFailure(Throwable caught) {
                            System.out.println("Problem saving citizen");

                        }

                        @Override
                        public void onSuccess(Boolean result) {
                            System.out.println("Citizen successfully saved");

                        }

                    });

                    service.saveCountry(country, new AsyncCallback<Boolean>(){

                        @Override
                        public void onFailure(Throwable caught) {
                            System.out.println("Problem saving country");

                        }

                        @Override
                        public void onSuccess(Boolean result) {
                            System.out.println("Country successfully saved");

                        }
                    });

...

– el servicio proporciona una simple GWT-RPC llamada al servidor

De servicio en el servidor:

@Service("componentService")
public class ComponentServiceImpl implements ComponentService{

    @Autowired
    private CountryDAO daoCnt;

    @Autowired
    private CitizenDAO daoCtz;

    @Transactional(readOnly=false)
    @Override
    public boolean saveCitizen(Citizen citizen) {
        daoCtz.saveOrUpdate(citizen);
        return true;
    }

    @Transactional(readOnly=false)
    @Override
    public boolean saveCountry(Country country) {
        daoCnt.saveOrUpdate(country);
        return true;
    }
}

Ahora SpringDAOs:

CitizenDAO:

@Repository
public class CitizenDAO {

...
    public void saveOrUpdate(Citizen citizen){
        sessionFactory.getCurrentSession().saveOrUpdate(citizen);
    }
...

CountryDAO:

@Repository
public class CountryDAO {

...
    public void saveOrUpdate(Country country){
        sessionFactory.getCurrentSession().saveOrUpdate(country);
    }
...

Finalmente

Citizen.hbm.xml:

<hibernate-mapping>
    <class name="sk.jakub.mod.shared.model.Citizen" table="citizen" catalog="modeldb">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="identity" />
        </id>
        <many-to-one name="country" class="sk.jakub.mod.shared.model.Country" fetch="select">
            <column name="Country_id" not-null="true" />
        </many-to-one>
        <property name="name" type="string">
            <column name="name" length="45" not-null="true" />
        </property>
        <property name="surname" type="string">
            <column name="surname" length="45" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

Country.hbm.xml:

<hibernate-mapping>
    <class name="sk.jakub.mod.shared.model.Country" table="country" catalog="modeldb">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="name" length="45" not-null="true" />
        </property>
        <property name="population" type="int">
            <column name="population" not-null="true" />
        </property>
        <set name="citizens" table="citizen" inverse="true" lazy="true" fetch="select">
            <key>
                <column name="Country_id" not-null="true" />
            </key>
            <one-to-many class="sk.jakub.mod.shared.model.Citizen" />
        </set>
    </class>
</hibernate-mapping>

No he enumerado Citizen.java y Country.java debido a que sólo están básica POJOs (si es necesario voy a proveer de ellos).

Cuando ejecuto mi aplicación y quiero guardar mis datos en la base de datos puedo obtener el siguiente error:

org.hibernate.PropertyValueException: not-null property references a null or transient value: sk.jakub.mod.shared.model.Citizen.country 

Que no puedo averiguar dónde está el problema. Yo estaba tratando también en lugar de saveOrUpdate método, persisten método. O también para cambiar el orden de guardar en la base de datos. Nada parecía funcionar.

Muchas gracias por la ayuda 🙂 Si es necesario, puedo publicar más el código de mi aplicación.

EDITAR:
código para Citizen.java:

public class Citizen implements java.io.Serializable {

    private static final long serialVersionUID = -3102863479088406293L;
    private Integer id;
    private Country country;
    private String name;
    private String surname;

    public Citizen() {
    }

    public Citizen(Country country, String name, String surname) {
        this.country = country;
        this.name = name;
        this.surname = surname;
    }

    public Integer getId() {
        return this.id;
    }

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

    public Stat getCountry() {
        return this.country;
    }

    public void setCountry(Country country) {
        this.country = country;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return this.surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }
}

Country.java:

public class Country implements java.io.Serializable {
private static final long serialVersionUID = -4085805854508658303L;
private Integer id;
private String name;
private int population;
private Set<Citizen> citizens = new HashSet<Citizen>();
public Country() {
}
public Country(String name, int population) {
this.name = name;
this.population = population;
}
public Country(String name, int population, Set<Citizen> citizens) {
this.name = name;
this.population = population;
this.citizens = citizens;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getPopulation() {
return this.population;
}
public void setPopulation(int population) {
this.population = population;
}
public Set<Citizen> getCitizens() {
return this.citizens;
}
public void setCitizens(Set<Citizen> citizens) {
this.citizens = citizens;
}
}

Además, he comprobado manualmente la base de datos y el País está a salvo, pero el ciudadano no lo es.

  • Parece que están tratando de salvar a un Ciudadano POJO que tiene un valor null País objeto. Se puede incluir el código de País y el Ciudadano?
  • procesa tanto código fuente agregó 🙂
InformationsquelleAutor Reshi | 2012-09-18

2 Comentarios

  1. 2

    Estoy viendo que va a crear un Ciudadano antes de crear un país. También tanto a las llamadas de servicio debe estar en la misma transacción, para el conjunto de la operación atómica. El COUNTRY_ID parece ser un auto id generado creo. Así que una vez que cree que el país puede adjuntar a un ciudadano, pero que la pila de llamadas muestra son la creación de un ciudadano que tiene un País objeto de que no tiene un id. Esto es sólo mi suposición. Usted puede tratar de poner tanto las llamadas en la misma transacción y también intentar la creación de un País y adjuntar el país ejemplo para el Ciudadano.

    • muchas gracias. El problema era que en la transacción. Guardar por primera vez a la base de datos fue en una transacción, el otro sino fue en otro. Y ahí estaba el problema. Por lo tanto, si tehre son las dependencias de éste, que tienen que ir en una transacción. 🙂
    • Sí que debería debajo de una campana de transacción!!!! 🙂
  2. 0

    Por favor, compruebe si se ha implementado el equals y hashcode compareTo (si procede) los métodos correctamente. Recientemente me he enfrentado a este problema y lo resolvió a través de la correcta implementación de estos.

Dejar respuesta

Please enter your comment!
Please enter your name here