[java] ¿Cómo persistir una propiedad de tipo List <String> en JPA?



Answers

Esta respuesta se realizó antes de las implementaciones JPA2, si está utilizando JPA2, consulte la respuesta ElementCollection anterior:

Las listas de objetos dentro de un objeto modelo generalmente se consideran relaciones "OneToMany" con otro objeto. Sin embargo, una Cadena no es (por sí misma) un cliente permitido de una relación de Uno a Muchos, ya que no tiene una ID.

Por lo tanto, debe convertir su lista de cadenas a una lista de objetos JPA de clase argumental que contengan una ID y una cadena. Podría utilizar potencialmente la Cadena como ID, lo que ahorraría un poco de espacio en su tabla tanto al eliminar el campo ID como al consolidar filas donde las Cadenas son iguales, pero perdería la capacidad de ordenar los argumentos nuevamente en su orden original. (ya que no almacenó ninguna información de pedido).

Alternativamente, podría convertir su lista en @Transient y agregar otro campo (argStorage) a su clase que sea VARCHAR () o CLOB. Luego deberá agregar 3 funciones: 2 de ellas son iguales y debe convertir su lista de Cadenas en una sola Cadena (en argStorage) delimitada de manera tal que pueda separarlas fácilmente. Anota estas dos funciones (que cada una haga lo mismo) con @PrePersist y @PreUpdate. Finalmente, agregue la tercera función que divide el argStorage en la lista de cadenas nuevamente y anótelo @PostLoad. Esto mantendrá su CLOB actualizado con las cadenas cada vez que vaya a almacenar el Comando, y mantendrá el campo argStorage actualizado antes de almacenarlo en el DB.

Todavía sugiero hacer el primer caso. Es una buena práctica para relaciones reales después.

Question

¿Cuál es la forma más inteligente de obtener una entidad con un campo de tipo Lista persistida?

Command.java

package persistlistofstring;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Persistence;

@Entity
public class Command implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;
    @Basic
    List<String> arguments = new ArrayList<String>();

    public static void main(String[] args) {
        Command command = new Command();

        EntityManager em = Persistence
                .createEntityManagerFactory("pu")
                .createEntityManager();
        em.getTransaction().begin();
        em.persist(command);
        em.getTransaction().commit();
        em.close();

        System.out.println("Persisted with id=" + command.id);
    }
}

Este código produce:

> Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named pu: Provider named oracle.toplink.essentials.PersistenceProvider threw unexpected exception at create EntityManagerFactory: 
> oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException
> Local Exception Stack: 
> Exception [TOPLINK-30005] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException
> Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7
> Internal Exception: javax.persistence.PersistenceException: Exception [TOPLINK-28018] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.EntityManagerSetupException
> Exception Description: predeploy for PersistenceUnit [pu] failed.
> Internal Exception: Exception [TOPLINK-7155] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
> Exception Description: The type [interface java.util.List] for the attribute [arguments] on the entity class [class persistlistofstring.Command] is not a valid type for a serialized mapping. The attribute type must implement the Serializable interface.
>         at oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:143)
>         at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:169)
>         at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:110)
>         at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
>         at persistlistofstring.Command.main(Command.java:30)
> Caused by: 
> ...



Tuve el mismo problema, así que invertí la posible solución, pero al final decidí implementar mi ';' lista separada de String.

así que tengo

// a ; separated list of arguments
String arguments;

public List<String> getArguments() {
    return Arrays.asList(arguments.split(";"));
}

De esta manera, la lista es fácilmente legible / editable en la tabla de la base de datos;




También podemos usar esto.

@Column(name="arguments")
@ElementCollection(targetClass=String.class)
private List<String> arguments;



Mi solución para este problema fue separar la clave principal con la clave externa. Si está utilizando eclipse e hizo los cambios anteriores, recuerde actualizar el explorador de la base de datos. Luego recrea las entidades de las tablas.




Related



Tags

java java   orm   jpa