PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách sao chép câu lệnh INSERT / UPDATE / DELETE bằng JPA và Hibernate

Bảng cơ sở dữ liệu

Giả sử bạn có hai bảng sau:

CREATE TABLE old_post (
    id int8 NOT NULL,
    title varchar(255),
    version int4 NOT NULL,
    PRIMARY KEY (id)
)
                                                  
CREATE TABLE post (
    id int8 NOT NULL,
    created_on date, 
    title varchar(255),
    version int4 NOT NULL,
    PRIMARY KEY (id)
)

Thực thể JPA

old_post bảng phải được sao chép với post mới hơn . Lưu ý rằng post bảng hiện có nhiều cột hơn bảng cũ.

Chúng tôi chỉ cần ánh xạ Post thực thể:

@Entity(name = "Post")
@Table(name = "post")
public static class Post {

    @Id
    private Long id;

    private String title;

    @Column(name = "created_on")
    private LocalDate createdOn = LocalDate.now();

    @Version
    private int version;

    //Getters and setters omitted for brevity
}

Trình nghe sự kiện ngủ đông

Bây giờ, chúng ta phải đăng ký 3 trình xử lý sự kiện để chặn các hoạt động INSERT, UPDATE và DELETE cho Post thực thể.

Chúng ta có thể thực hiện việc này thông qua các trình nghe sự kiện sau:

public class ReplicationInsertEventListener 
        implements PostInsertEventListener {
 
    public static final ReplicationInsertEventListener INSTANCE = 
        new ReplicationInsertEventListener();
 
    @Override
    public void onPostInsert(
            PostInsertEvent event) 
            throws HibernateException {
        final Object entity = event.getEntity();
 
        if(entity instanceof Post) {
            Post post = (Post) entity;
 
            event.getSession().createNativeQuery(
                "INSERT INTO old_post (id, title, version) " +
                "VALUES (:id, :title, :version)")
            .setParameter("id", post.getId())
            .setParameter("title", post.getTitle())
            .setParameter("version", post.getVersion())
            .setFlushMode(FlushMode.MANUAL)
            .executeUpdate();
        }
    }
 
    @Override
    public boolean requiresPostCommitHanding(
            EntityPersister persister) {
        return false;
    }
}

public class ReplicationUpdateEventListener 
    implements PostUpdateEventListener {

    public static final ReplicationUpdateEventListener INSTANCE = 
        new ReplicationUpdateEventListener();

    @Override
    public void onPostUpdate(
            PostUpdateEvent event) {
        final Object entity = event.getEntity();

        if(entity instanceof Post) {
            Post post = (Post) entity;

            event.getSession().createNativeQuery(
                "UPDATE old_post " +
                "SET title = :title, version = :version " +
                "WHERE id = :id")
            .setParameter("id", post.getId())
            .setParameter("title", post.getTitle())
            .setParameter("version", post.getVersion())
            .setFlushMode(FlushMode.MANUAL)
            .executeUpdate();
        }
    }

    @Override
    public boolean requiresPostCommitHanding(
            EntityPersister persister) {
        return false;
    }
}

public class ReplicationDeleteEventListener 
        implements PreDeleteEventListener {

    public static final ReplicationDeleteEventListener INSTANCE = 
        new ReplicationDeleteEventListener();

    @Override
    public boolean onPreDelete(
            PreDeleteEvent event) {
        final Object entity = event.getEntity();

        if(entity instanceof Post) {
            Post post = (Post) entity;

            event.getSession().createNativeQuery(
                "DELETE FROM old_post " +
                "WHERE id = :id")
            .setParameter("id", post.getId())
            .setFlushMode(FlushMode.MANUAL)
            .executeUpdate();
        }

        return false;
    }
}

Có thể đăng ký 3 trình nghe sự kiện bằng Integrator Hibernate :

public class ReplicationEventListenerIntegrator 
        implements Integrator {

    public static final ReplicationEventListenerIntegrator INSTANCE = 
        new ReplicationEventListenerIntegrator();

    @Override
    public void integrate(
            Metadata metadata,
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {

        final EventListenerRegistry eventListenerRegistry =
                serviceRegistry.getService(EventListenerRegistry.class);

        eventListenerRegistry.appendListeners(
            EventType.POST_INSERT, 
            ReplicationInsertEventListener.INSTANCE
        );

        eventListenerRegistry.appendListeners(
            EventType.POST_UPDATE, 
            ReplicationUpdateEventListener.INSTANCE
        );

        eventListenerRegistry.appendListeners(
            EventType.PRE_DELETE, 
            ReplicationDeleteEventListener.INSTANCE
        );
    }

    @Override
    public void disintegrate(
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {

    }
}

Và, để hướng dẫn Hibernate sử dụng Integrator tùy chỉnh này , bạn cần thiết lập hibernate.integrator_provider thuộc tính cấu hình:

<property name="hibernate.integrator_provider"
          value="com.vladmihalcea.book.hpjp.hibernate.listener.ReplicationEventListenerIntegrator "/>

Thời gian kiểm tra

Bây giờ, khi duy trì một Post thực thể:

Post post1 = new Post();
post1.setId(1L);
post1.setTitle(
    "The High-Performance Java Persistence book is to be released!"
);

entityManager.persist(post1);

Hibernate sẽ thực thi các câu lệnh SQL INSERT sau:

Query:["INSERT INTO old_post (id, title, version) VALUES (?, ?, ?)"], Params:[(1, The High-Performance Java Persistence book is to be released!, 0)]

Query:["insert into post (created_on, title, version, id) values (?, ?, ?, ?)"], Params:[(2018-12-12, The High-Performance Java Persistence book is to be released!, 0, 1)]

Khi thực hiện một giao dịch khác cập nhật một Post hiện có thực thể và tạo một Post mới thực thể:

Post post1 = entityManager.find(Post.class, 1L);
post1.setTitle(post1.getTitle().replace("to be ", ""));

Post post2 = new Post();
post2.setId(2L);
post2.setTitle(
    "The High-Performance Java Persistence book is awesome!"
);

entityManager.persist(post2);

Hibernate sao chép tất cả các hành động vào old_post bảng cũng như:

 Query:["select tablerepli0_.id as id1_1_0_, tablerepli0_.created_on as created_2_1_0_, tablerepli0_.title as title3_1_0_, tablerepli0_.version as version4_1_0_ from post tablerepli0_ where tablerepli0_.id=?"], Params:[(1)]

 Query:["INSERT INTO old_post (id, title, version) VALUES (?, ?, ?)"], Params:[(2, The High-Performance Java Persistence book is awesome!, 0)]

 Query:["insert into post (created_on, title, version, id) values (?, ?, ?, ?)"], Params:[(2018-12-12, The High-Performance Java Persistence book is awesome!, 0, 2)]

 Query:["update post set created_on=?, title=?, version=? where id=? and version=?"], Params:[(2018-12-12, The High-Performance Java Persistence book is released!, 1, 1, 0)]

 Query:["UPDATE old_post SET title = ?, version = ? WHERE id = ?"], Params:[(The High-Performance Java Persistence book is released!, 1, 1)]

Khi xóa một Post thực thể:

Post post1 = entityManager.getReference(Post.class, 1L);
entityManager.remove(post1);

old_post bản ghi cũng được xóa:

Query:["DELETE FROM old_post WHERE id = ?"], Params:[(1)]
Query:["delete from post where id=? and version=?"], Params:[(1, 1)]

Mã có sẵn trên

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để đảm bảo các mục nhập có phạm vi thời gian không trùng lặp?

  2. Chọn các cột từ lệnh gọi hàm trong lõi sqlalchemy

  3. Sự cố với phạm vi thời gian vô hạn trong Rails

  4. SQL 'AT TIME ZONE', truy vấn rộng và với biểu thức 'CHỌN' tất cả các cột (tên bảng. *)

  5. LỖI:truy vấn con trong FROM không thể tham chiếu đến các quan hệ khác có cùng cấp độ truy vấn