1. 程式人生 > >Hibernate 5 入門指南-基於Envers

Hibernate 5 入門指南-基於Envers

  1. 首先建立\META-INF\persistence.xml配置檔案並做簡單的配置

    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
                version="2.0">

       <persistence-unit name="org.hibernate.tutorial.envers">
           <description>
              Persistence unit for the JPA tutorial of the Hibernate Getting Started Guide
           </description>

           <properties>
               <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" />
               <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/databaseName?useSSL=false&amp;serverTimezone=UTC&amp;verifyServerCertifate=false&amp;allowPublicKeyRetrieval=true" />
               <property name="javax.persistence.jdbc.user" value="root" />
               <property name="javax.persistence.jdbc.password" value="passwd" />
    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
               <property name="hibernate.show_sql" value="true" />
               <property name="hibernate.format_sql" value="true"/>
               <property name="hibernate.hbm2ddl.auto" value="create" />
           </properties>

       </persistence-unit>

    </persistence>
  2. 建立實體Java類

    import java.util.Date;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;

    import org.hibernate.annotations.GenericGenerator;
    import org.hibernate.envers.Audited;

    @Entity
    @Table( name = "EVENTS" )
    @Audited  // <--- this tell Envers to audit (track changes to) this entity
    public class Event {
       private Long id;

       private String title;
       private Date date;

    public Event() {
    // this form used by Hibernate
    }

    public Event(String title, Date date) {
    // for application use, to create new events
    this.title = title;
    this.date = date;
    }

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
       public Long getId() {
    return id;
      }

       private void setId(Long id) {
    this.id = id;
      }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "EVENT_DATE")
       public Date getDate() {
    return date;
      }

       public void setDate(Date date) {
    this.date = date;   }​    public String getTitle() { return title;   }​    public void setTitle(String title) { this.title = title;   }​ @Override public int hashCode() { int result = title.hashCode(); result = 31 * result + date.hashCode(); return result; }}
  3. 向META-INF/persistence.xml檔案中新增對映資訊

    <class>類路徑.Event</class>
  4. JUnit測試測試程式

    import java.util.Date;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;

    import junit.framework.TestCase;

    import org.hibernate.envers.AuditReader;
    import org.hibernate.envers.AuditReaderFactory;

    /**
    * Illustrates the set up and use of Envers.
    * <p>
    * This example is different from the others in that we really need to save multiple revisions to the entity in
    * order to get a good look at Envers in action.
    *
    * @author Steve Ebersole
    */
    public class EnversIllustrationTest extends TestCase {
    private EntityManagerFactory entityManagerFactory;

    @Override
    protected void setUp() throws Exception {
    // like discussed with regards to SessionFactory, an EntityManagerFactory is set up once for an application
    // IMPORTANT: notice how the name here matches the name we gave the persistence-unit in persistence.xml!
    entityManagerFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.envers" );
    }

    @Override
    protected void tearDown() throws Exception {
    entityManagerFactory.close();
    }

    public void testBasicUsage() {
    // create a couple of events
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();
    entityManager.persist( new Event( "Our very first event!", new Date() ) );
    entityManager.persist( new Event( "A follow up event", new Date() ) );
    entityManager.getTransaction().commit();
    entityManager.close();

    // now lets pull events from the database and list them
    entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();
           List<Event> result = entityManager.createQuery( "from Event", Event.class ).getResultList(); for ( Event event : result ) { System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() ); }        entityManager.getTransaction().commit();        entityManager.close();​ // so far the code is the same as we have seen in previous tutorials. Now lets leverage Envers...​ // first lets create some revisions entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Event myEvent = entityManager.find( Event.class, 2L ); // we are using the increment generator, so we know 2 is a valid id myEvent.setDate( new Date() ); myEvent.setTitle( myEvent.getTitle() + " (rescheduled)" );        entityManager.getTransaction().commit();        entityManager.close();​ // and then use an AuditReader to look back through history entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); myEvent = entityManager.find( Event.class, 2L ); assertEquals( "A follow up event (rescheduled)", myEvent.getTitle() ); AuditReader reader = AuditReaderFactory.get( entityManager ); Event firstRevision = reader.find( Event.class, 2L, 1 ); assertFalse( firstRevision.getTitle().equals( myEvent.getTitle() ) ); assertFalse( firstRevision.getDate().equals( myEvent.getDate() ) ); Event secondRevision = reader.find( Event.class, 2L, 2 ); assertTrue( secondRevision.getTitle().equals( myEvent.getTitle() ) ); assertTrue( secondRevision.getDate().equals( myEvent.getDate() ) ); entityManager.getTransaction().commit();        entityManager.close(); }}
  5. 執行測試

    Hibernate: 
    十一月 01, 2018 2:59:17 下午 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
    INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@1761fc10] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
       
       drop table if exists EVENTS
    Hibernate:
       
       create table EVENTS (
          id bigint not null,
           EVENT_DATE datetime(6),
           title varchar(255),
           primary key (id)
      ) engine=InnoDB
    十一月 01, 2018 2:59:17 下午 org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
    INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@1379327f] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
    十一月 01, 2018 2:59:18 下午 org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
    INFO: HHH000476: Executing import script 'org.hiber[email protected]7de51c1f'
    Hibernate:
       select
           max(id)
       from
           EVENTS
    Hibernate:
       insert    into        EVENTS       (EVENT_DATE, title, id)    values       (?, ?, ?)Hibernate:    insert    into        EVENTS       (EVENT_DATE, title, id)    values       (?, ?, ?)十一月 01, 2018 2:59:18 下午 org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateServiceINFO: HHH000397: Using ASTQueryTranslatorFactoryHibernate:    select        event0_.id as id1_0_,        event0_.EVENT_DATE as EVENT_DA2_0_,        event0_.title as title3_0_    from        EVENTS event0_Event (2018-11-01 14:59:18.261) : Our very first event!Event (2018-11-01 14:59:18.292) : A follow up event​十一月 01, 2018 2:59:18 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop