Tengo una clase llamada SynonymMapping que tiene una colección de valores asignada como CollectionOfElements

@Entity(name = "synonymmapping")
public class SynonymMapping {

    @Id private String keyId;

    //@CollectionOfElements(fetch = FetchType.EAGER)
    @CollectionOfElements
    @JoinTable(name="synonymmappingvalues", joinColumns={@JoinColumn(name="keyId")})
    @Column(name="value", nullable=false)
    @Sort(type=SortType.NATURAL)
    private SortedSet<String> values;

    public SynonymMapping() {
        values = new TreeSet<String>();
    }

    public SynonymMapping(String key, SortedSet<String> values) {
        this();
        this.keyId = key;
        this.values = values;
    }

    public String getKeyId() {
        return keyId;
    }

    public Set<String> getValues() {
        return values;
    }
}

Tengo una prueba en la que guardo las dos SynonymMapping objetos a la base de datos y, a continuación, pedir a la base de datos de todos los salvos SynonymMapping objetos, a la espera de recibir los dos objetos que almacena.

Cuando yo cambie la asignación de valores a ser impacientes (como se muestra en el código por el comentario de la línea) y vuelva a ejecutar la prueba, recibo cuatro partidos.

Me han limpiado la base de datos entre carreras y puedo duplicar este problema intercambio entre ansiosos y perezoso.

Creo que tiene que ver con las combinaciones que se hibernate crea debajo, pero no puedo encontrar una respuesta definitiva en línea.

¿Alguien puede decirme por qué una ansiosa fetch es la duplicación de los objetos?

Gracias.

  • Cada uno, con la Excepción de «Más de una fila con el identificador se encontró» debe saber acerca de este. Realmente repuestos un montón de horas sin saber qué diablos está pasando mal. Ver a @user176668 respuesta!!
InformationsquelleAutor Rachel | 2009-07-07

6 Comentarios

  1. 29

    Generalmente no es una buena idea para hacer cumplir con ganas de ir a buscar en la asignación – es mejor especificar con ganas combinaciones apropiadas de consultas (a menos que estés 100% seguro de que en todas las circunstancias de su objeto no tengan sentido /ser válido sin que la recolección de ser poblado).

    La razón por la que usted está consiguiendo duplicados es porque Hibernate internamente se une a su raíz y de la colección de tablas. Tenga en cuenta que realmente son duplicados, por ejemplo, para 2 SynonymMappings con 3 colección de elementos de cada uno de los que obtendría de 6 resultados (2×3), 3 copias de cada SynonymMapping entidad. Así que la solución más sencilla consiste en envolver los resultados en un Conjunto asegurando con ello que sea único.

    • Pero, ¿por qué puede Hibernar filtro no estas, no puedo ver por qué usted quiere que esto esta como esta.
    • Puedo confirmar que funciona. Yo estaba usando una Colección<T> simplemente, en general, y que fue un error.
  2. 65

    Entré en el mismo problema: cuando se establece la FetchType.Con GANAS de un @CollectionOfElements, la Hibernación intenta conseguir todo en una sola toma, es decir, con una sola consulta para cada entrada de elemento vinculado a un «maestro» del objeto. Este problema puede ser resuelto con éxito a un costo de N+1 de la consulta, si se agrega el @Fetch (FetchMode.SELECCIONE) anotación a su colección.
    En mi caso yo quería tener una MediaObject entidad con una colección de elementos de metadatos (códec de vídeo, el codec de audio, tamaños, etc.). La asignación de un metadataItems colección se ve de la siguiente manera:

     
    @CollectionOfElements (targetElement = String.class, fetch = FetchType.Con GANAS) 
    @JoinTable(name = "mo_metadata_item", joinColumns = @JoinColumn(name = "media_object_id")) 
    @MapKey(columnas = @Column(name = "nombre")) 
    @Column (name = "valor"). 
    @Fetch (FetchMode.SELECCIONE) 
    Mapa privado<String, String> metadataItems = new HashMap<String, String>(); 
    
    • Muchas gracias por esto.
    • Me gustó la solución, porque no es necesario para envolver el resultado de un Conjunto para obtener su unicidad.
    • Gracias SOOOOO mucho por esto !!! Salvó mi día 🙂
    • Gracias!!! Salvó mi día (2)!!
    • puede también ser causada por el almacenamiento en caché como EHcache?
    • Esta solución funciona muy bien, sin embargo, es dependiente de la implementación.
    • Gracias SOOOOO mucho por esto !!! Salvó mi día 🙂 2
    • Este es uno de los que trabajó para mí. Gracias!
    • Gracias. He hecho un montón de búsqueda sobre él. Cada cuerpo se dice que el uso Conjunto.
    • A mí me funciona. Muy mal @Fetch no es un JPA anotación, pero a quién le importa. Me pregunto qué se supone que usted debe hacer cuando se utiliza puro JPA, aunque. Es un poco frustrante.
    • Tomó las edades para la depuración de esto, y aún más tiempo para encontrar una respuesta que no era un tutorial sobre la aplicación de las colecciones. Gracias por compartir.

  3. 7

    Me he enfrentado a este problema y lo resolví utilizando

    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

    Esto elimina los duplicados que son causados por la unión hecha para el niño tablas.

  4. 2

    Usted podría utilizar un SELECT DISTINCT (Hibernate Query Language) de la cláusula como sigue

    SELECT DISTINCT synonym FROM SynonymMapping synonym LEFT JOIN FETCH synonym.values

    Cláusula DISTINCT elimina referencias duplicadas en modo de Hibernación.

    A pesar de que ambos componentes y el tipo de valor de la colección, tiene su ciclo de vida vinculado a la entidad propietaria de la clase, usted debe declarar en la cláusula select para recuperar de ellos. (LEFT JOIN FETCH sinónimo.los valores)

    ChssPly76 la respuesta es otro enfoque, pero no se olvide de reemplazar equals y hashcode método de acuerdo para Establecer semántica

    saludos,

    • Me preguntaba acerca de por qué esto sucede y el por qué de la decisión de diseño fue tomado de hibernate para responder como este más de las diferentes maneras de conseguir alrededor de él.
  5. 0

    He conseguido a través de simplemente agregar

    session.createCriteria(ModelClass.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

    Esto ayuda a eliminar duplicados.

Dejar respuesta

Please enter your comment!
Please enter your name here