2010-05-17 9 views
7

Cuando intento hacer una entityManager.remove (instancia) el proveedor JPA subyacente emite una operación de eliminación separada en cada una de las entidades GroupUser. Siento que esto no es correcto desde la perspectiva del rendimiento, ya que si un grupo tiene 1000 usuarios habrá 1001 llamadas emitidas para eliminar el grupo completo y su entidad de usuario de grupo.La operación de eliminación de JPA entitymanager no se realiza

¿Tendría más sentido escribir una consulta con nombre para eliminar todas las entradas en la tabla groupuser (por ejemplo, delete from group_user where group_id =?), Por lo que tendría que hacer solo 2 llamadas para eliminar el grupo.

@Entity 
@Table(name = "tbl_group") 

public class Group { 

    @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    @Cascade(value = DELETE_ORPHAN) 
    private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0); 

Respuesta

8

La respuesta simple es sí. Si desea eliminar un Group y sabe que hay toneladas de registros en la tabla GroupUser, entonces es mucho mejor crear una consulta de eliminación que lo haga todo en un lote en lugar de uno y uno.

Si no tiene una conexión en cascada en la base de datos subyacente (o incluso si lo hace), es una buena práctica hacerlo en el orden correcto.

Así que elimine primero el GroupUser.
Suponiendo que tiene un objeto Group que desea eliminar.

int numberDeleted = entityManager.createQuery("DELETE FROM GroupUser gu WHERE gu.group.id=:id").setParameter("id",group.getId()).executeUpdate(); 

La vuelta int muestra cuántos registros fueron eliminados.

Ahora usted puede finalmente eliminar Group

entityManager.remove(group); 
entityManager.flush(); 

ACTUALIZACIÓN

parece que @OnDelete en el @OneToMany hace el truco

+0

Es extraño que no pueda confiar en la opción cascade = DELETE según la especificación JPA, ya que borra todas las instancias GroupUser 1 por 1. Esto implica que tengo que escribir código personalizado para optimizar la eliminación de entradas. – Sam

+2

@Samuel. Hice una pregunta muy similar el otro día. Puede encontrarlo aquí: http://stackoverflow.com/questions/2856460/hibernate-doesnt-generate-cascade Y la sugerencia de usar @OnDelete en lugar de cascade podría significar que no elimina las instancias 1 por 1 . Podrías intentarlo. Aunque no lo he probado todavía. –

+0

@Shervin - @OnDelete funciona como un amuleto, de alguna manera se perdió al usarlo. Sugeriría que agregue soporte para esto también para todas las anotaciones de @OneToMany. – Sam

2

Desde el GroupUser pueden tener cascadas, así, no creo que hay una manera de decirle a hibernar a lotes eliminarlos a través de la configuración.

Pero si está seguro No hay cascade=DELETE en GroupUser, se sienten libres para emitir un/APP-QL consulta HQL:

DELETE FROM GroupUser WHERE group=:group 

Si hay cascadas, las manejan con una consulta así.

+0

GroupUser no tiene ninguna entrada en cascada. Es extraño que no pueda confiar en la opción cascade = DELETE según la especificación JPA, ya que el proveedor ORM subyacente elimina todas las instancias GroupUser 1 por 1. Esto implica que tengo que escribir código personalizado para optimizar la eliminación de entradas. – Sam

Cuestiones relacionadas