java of objects - ¿Cómo persistir una propiedad de tipo List <String> en JPA?




5 Answers

Utilice alguna implementación de JPA 2: agrega una anotación @ElementCollection, similar a la de Hibernate, que hace exactamente lo que necesita. Hay un ejemplo here .

Editar

Como se menciona en los comentarios a continuación, la implementación correcta de JPA 2 es

javax.persistence.ElementCollection

@ElementCollection
Map<Key, Value> collection;

Ver: http://docs.oracle.com/javaee/6/api/javax/persistence/ElementCollection.html

entities @elementcollection

¿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: [email protected]
> 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: 
> ...



Según Java Persistence con Hibernate

mapeo de colecciones de tipos de valores con anotaciones [...]. En el momento de escribir esto, no es parte del estándar de Java Persistence

Si estuviera usando Hibernate, podría hacer algo como:

@org.hibernate.annotations.CollectionOfElements(
    targetElement = java.lang.String.class
)
@JoinTable(
    name = "foo",
    joinColumns = @JoinColumn(name = "foo_id")
)
@org.hibernate.annotations.IndexColumn(
    name = "POSITION", base = 1
)
@Column(name = "baz", nullable = false)
private List<String> arguments = new ArrayList<String>();

Actualización: Nota, esto ahora está disponible en JPA2.




Cuando uso la implementación Hibernate de JPA, descubrí que simplemente declarar el tipo como ArrayList en lugar de List permite que hibernate almacene la lista de datos.

Claramente, esto tiene una serie de desventajas en comparación con la creación de una lista de objetos Entity. Sin carga diferida, sin capacidad para hacer referencia a las entidades en la lista desde otros objetos, tal vez más dificultad en la construcción de consultas a la base de datos. Sin embargo, cuando se trata de listas de tipos bastante primitivos que siempre querrá buscar ansiosamente junto con la entidad, entonces este enfoque me parece bien.

@Entity
public class Command implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;

    ArrayList<String> arguments = new ArrayList<String>();


}



Ok, sé que es un poco tarde. Pero para esas almas valientes que verán esto a medida que pase el tiempo.

Como está escrito en la documentation :

@Basic: el tipo más simple de asignación a una columna de base de datos. La anotación Básica se puede aplicar a una propiedad persistente o variable de instancia de cualquiera de los siguientes tipos: tipos primitivos de Java, [...], enumeraciones y cualquier otro tipo que implemente java.io.Serializable.

La parte importante es el tipo que implementa Serializable

Así que, con mucho, la solución más simple y fácil de usar es simplemente usar ArrayList en lugar de List (o cualquier contenedor serializable):

@Basic
ArrayList<Color> lovedColors;

@Basic
ArrayList<String> catNames;

Sin embargo, recuerde que esto utilizará la serialización del sistema, por lo que vendrá con algún precio, como por ejemplo:

  • si el modelo de objeto serializado cambiara, es posible que no pueda restaurar los datos

  • Se agrega una pequeña sobrecarga por cada elemento almacenado.

En breve

es bastante simple almacenar banderas o pocos elementos, pero no lo recomendaría para almacenar datos que puedan crecer a gran escala.




La respuesta de Thiago es correcta, al agregar una muestra más específica a la pregunta, @ElementCollection creará una nueva tabla en su base de datos, pero sin mapear dos tablas, significa que la colección no es una colección de entidades, sino una colección de tipos simples (cadenas, etc. .) o una colección de elementos incrustables (clase anotada con @Embeddable ).

Aquí está la muestra para persistir la lista de String

@ElementCollection
private Collection<String> options = new ArrayList<String>();

Aquí está la muestra para persistir en la lista de objetos personalizados

@Embedded
@ElementCollection
private Collection<Car> carList = new ArrayList<Car>();

Para este caso, necesitamos hacer una clase Embebible

@Embeddable
public class Car {
}



Related


Tags

java   orm   jpa