Saltar al contenido

Cómo hacer una copia profunda de una entidad de Hibernate mientras se usa un identificador de entidad recién generado

La guía paso a paso o código que encontrarás en este post es la solución más eficiente y efectiva que hallamos a esta inquietud o problema.

Simplemente recupere el objeto, sepárelo, establezca la identificación en null y persistirlo.

MyEntity clone = entityManager.find(MyEntity.class, ID);
entityManager.detach(clone);
clone.setId(null);
entityManager.persist(clone);

Si su objeto tiene relaciones oneToMany, tendrá que repetir la operación para todos los hijos pero configurando su ID de objeto principal (generado después del persist llamada) en lugar de null.

Por supuesto, tendrá que eliminar cualquier CASCADE persist en sus relaciones OneToMany porque, de lo contrario, su persistencia creará duplicados de todos los niños en fallas de restricción DB o fk.

También estoy trabajando con Hibernate y obtuve el mismo requisito que usted. Lo que seguí fue implementar Cloneable. A continuación se muestra un ejemplo de código de cómo hacerlo.

class Person implements Cloneable 

        private String firstName;
        private String lastName;

        public Object clone() 

            Person obj = new Person();
            obj.setFirstName(this.firstName);
            obj.setLastName(this.lastName);

            return obj;
        

        public String getFirstName() 
            return firstName;
        

        public void setFirstName(String firstName) 
            this.firstName = firstName;
        

        public String getLastName() 
            return lastName;
        

        public void setLastName(String lastName) 
            this.lastName = lastName;
        
    

O podría ir a una solución basada en la reflexión, pero no lo recomendaré. Consulte este sitio web para obtener más detalles.

Utilizando detach o la clonación profunda, como sugieren otros, no es el camino a seguir cuando se trata de clonar una entidad. Si intenta hacer que este proceso sea completamente automático, se perderá el punto de que no todos attributes vale la pena duplicar.

Por lo tanto, es mejor usar un constructor de copias y controlar exactamente lo que attributes necesita ser clonado.

Entonces, si tienes un Post entidad como esta:

@Entity(name = "Post")
@Table(name = "post")
public class Post 
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String title;
 
    @OneToMany(
        mappedBy = "post",
        cascade = CascadeType.ALL, 
        orphanRemoval = true
    )
    private List comments = new ArrayList<>();
 
    @OneToOne(
        mappedBy = "post",
        cascade = CascadeType.ALL, 
        orphanRemoval = true, 
        fetch = FetchType.LAZY
    )
    private PostDetails details;
 
    @ManyToMany
    @JoinTable(
        name = "post_tag",
        joinColumns = @JoinColumn(
            name = "post_id"
        ),
        inverseJoinColumns = @JoinColumn(
            name = "tag_id"
        )
    )
    private Set tags = new HashSet<>();
 
    //Getters and setters omitted for brevity
 
    public void addComment(
            PostComment comment) 
        comments.add(comment);
        comment.setPost(this);
    
 
    public void addDetails(
            PostDetails details) 
        this.details = details;
        details.setPost(this);
    
 
    public void removeDetails() 
        this.details.setPost(null);
        this.details = null;
    

No tiene sentido clonar el comments al duplicar un Post y usándolo como plantilla para uno nuevo:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.details
    join fetch p.tags
    where p.title = :title
    """, Post.class)
.setParameter(
    "title", 
    "High-Performance Java Persistence, 1st edition"
)
.getSingleResult();
 
Post postClone = new Post(post);
postClone.setTitle(
    postClone.getTitle().replace("1st", "2nd")
);
entityManager.persist(postClone);

Lo que necesitas agregar a la Post entidad es un constructor de copia:

/**
 * Needed by Hibernate when hydrating the entity 
 * from the JDBC ResultSet
 */
private Post() 
 
public Post(Post post) 
    this.title = post.title;
 
    addDetails(
        new PostDetails(post.details)
    );
 
    tags.addAll(post.getTags());

Por lo tanto, el constructor de copias es la mejor manera de abordar el problema de duplicación/clonación de entidades.

Sección de Reseñas y Valoraciones

Recuerda algo, que te concedemos explicar tu experiencia .

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *