<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JPA &#8211; Pauls Blog</title>
	<atom:link href="https://sterl.org/category/java/jpa/feed/" rel="self" type="application/rss+xml" />
	<link>https://sterl.org</link>
	<description></description>
	<lastBuildDate>Sun, 06 Aug 2023 15:11:27 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
	<item>
		<title>JPA Model testing with Hibernate Statistics</title>
		<link>https://sterl.org/2021/08/jpa-model-testing-with-hibernate-statistics/</link>
					<comments>https://sterl.org/2021/08/jpa-model-testing-with-hibernate-statistics/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Sun, 01 Aug 2021 11:25:00 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Unit Test]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=925</guid>

					<description><![CDATA[Problem Often we write JPA Entity classes an have to ensure in a larger team that refactoring doesn&#8217;t create performance problems or logical errors in the entity model usual problems are: In your test]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>Often we write JPA Entity classes an have to ensure in a larger team that refactoring doesn&#8217;t create performance problems or logical errors in the entity model usual problems are:</p>



<ul class="wp-block-list">
<li>Missing fetch joins in Queries
<ul class="wp-block-list">
<li>Which leads to slow fetch joins</li>
</ul>
</li>



<li>Wrong direction of Entity relations 
<ul class="wp-block-list">
<li>which leads to updates after inserts</li>



<li>or even to deletes and reinserts of data</li>
</ul>
</li>



<li>Wrong transaction boundaries
<ul class="wp-block-list">
<li>Which leads to multiple transactions for one logical business operation</li>
</ul>
</li>
</ul>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Component
public class HibernateAsserts {
  private final Statistics statistics;

  public HibernateAsserts(EntityManager entityManager) {
    try (Session session = entityManager.unwrap(org.hibernate.Session.class)) {
      @SuppressWarnings(&quot;resource&quot;)
      SessionFactory factory = session.getSessionFactory();
      factory.getStatistics().setStatisticsEnabled(true);
      statistics = factory.getStatistics();
    }
  }
  
  public HibernateAsserts assertTrxCount(int expected) {
    long value = statistics.getTransactionCount();
    if (value != expected) {
      logSummary();
      fail(&quot;Expected &quot; + expected + &quot; TransactionCount, but found &quot; + value);
    }
    return this;
  }
  
  public HibernateAsserts assertInsertCount(int expected) {
    long value = statistics.getEntityInsertCount();
    if (value != expected) {
      logSummary();
      fail(&quot;Expected &quot; + expected + &quot; EntityInsertCount, but found &quot; + value);
    }
    return this;
  }

  public void reset() {
    statistics.clear();
  }

  public void logSummary() {
    statistics.logSummary();
  }
}</pre></div>



<h2 class="wp-block-heading">In your test</h2>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@SpringBootTest
class MyTestClassTest {

  @Autowired private SubjectUnderTest subject;
  @Autowired private HibernateAsserts hibernateAsserts;
  
  @Test
  void textMyBusinessMethod() {
    // GIVEN
    // custom data setup for the test

    // WHEN
    hibernateAsserts.reset(); // ensure the setup is not in the stats
    subject.runBusinessMethod();
    
    // THEN
    // any business asserts
    hibernateAsserts
      .assertTrxCount(1)
      .assertInsertCount(1);
  }
}</pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2021/08/jpa-model-testing-with-hibernate-statistics/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>JPA default entity listener</title>
		<link>https://sterl.org/2017/08/jpa-default-entity-listener/</link>
					<comments>https://sterl.org/2017/08/jpa-default-entity-listener/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Tue, 15 Aug 2017 10:52:10 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[entity-listeners]]></category>
		<category><![CDATA[Hibernate]]></category>
		<guid isPermaLink="false">http://sterl.org/?p=232</guid>

					<description><![CDATA[The problem Sometimes we want to register a default Entity Listeners which are called as soon an entity is persisted, without adding the&#160;@EntityListeners annotation to our classes, as in most cases we anyway provide interfaces so we can access data on the entity itself. The problem is, that we cannot annotate our entity listener with&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading"> The problem </h2>



<p> Sometimes we want to register a default Entity Listeners which are called as soon an entity is persisted, without adding the&nbsp;<code>@EntityListeners</code> annotation to our classes, as in most cases we anyway provide interfaces so we can access data on the entity itself. The problem is, that we cannot annotate our entity listener with any annotation, only the entity itself. </p>



<h2 class="wp-block-heading"> Solution </h2>



<p> In JPA we can provide entity mappings in the <code>orm.xml</code> which allows us to define default listeners which are executed on any entity. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;xml&quot;,&quot;mime&quot;:&quot;application/xml&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;XML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;xml&quot;}">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;entity-mappings xmlns=&quot;http://java.sun.com/xml/ns/persistence/orm&quot;
                 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
                 xsi:schemaLocation=&quot;http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd&quot;
                 version=&quot;2.1&quot;&gt;
    &lt;persistence-unit-metadata&gt;
        &lt;persistence-unit-defaults&gt;
            &lt;entity-listeners&gt;
                &lt;entity-listener class=&quot;org.sterl.example.EntityListener&quot;&gt;
                    &lt;!-- optional, annotations will work too --&gt;
                    &lt;pre-persist method-name=&quot;fooMethod&quot;/&gt; 
                &lt;/entity-listener&gt;
            &lt;/entity-listeners&gt;
        &lt;/persistence-unit-defaults&gt;
    &lt;/persistence-unit-metadata&gt;
&lt;/entity-mappings&gt;</pre></div>



<p>Furthermore, the body of the entity-listener may contain elements pre-persist to define method. </p>



<p><a rel="noreferrer noopener" href="https://github.com/sterlp/training/blob/master/hibernate/src/test/java/org/sterl/education/entitylistener/TimestampEntityListenerTest.java" target="_blank">Example On GitHub</a></p>



<h2 class="wp-block-heading"> Example</h2>



<p>Let&#8217;s assume we want to add to each entity an update time and a create time. We could, of course, implement a base entity, but as we should favor composition over inheritance &#8212; which would allow us to add even more common fields to the entity &#8212; we want to go with an embedded class. Let&#8217;s say <code>TimestampBE</code>. </p>



<h3 class="wp-block-heading">Embeddable time stamps</h3>



<p>This class adds to any entity the create date and update date. We just store UTC longs measured from 1970-01-01T00:00Z.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Embeddable @Getter @Setter
public class TimestampBE implements Serializable {
    @Column(name = &quot;create_date&quot;, nullable = false, updatable = false)
    private Long createDate;
    @Column(name = &quot;update_date&quot;, nullable = false, updatable = true)
    private Long updateDate;
}</pre></div>



<h3 class="wp-block-heading">Tag interface</h3>



<p>Next, we add an interface that allows us to tag any entity that has a timestamp.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">/**
 * Interface which marks an entity that it has the timestamp entity.
 */
public interface HasTimestamp {
    TimestampBE getTimestamp();
    void setTimestamp(TimestampBE timestamp);
}</pre></div>



<h3 class="wp-block-heading">Timestamp Entity Listener</h3>



<p>Now we have to define the behavior which sets us the create and update date in the live cycle of the entity. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">public class TimestampEntityListener {
    @PrePersist
    void prePersist(Object entity) {
        if (entity instanceof HasTimestamp) {
            TimestampBE timestamp = getTimestamp((HasTimestamp)entity);
            final long now = Clock.systemUTC().millis();
            timestamp.setCreateDate(now);
            timestamp.setUpdateDate(now);
        }
    }

    @PreUpdate
    void preUpdate(Object entity) {
        if (entity instanceof HasTimestamp) {
            TimestampBE timestamp = getTimestamp((HasTimestamp)entity);
            final long now = Clock.systemUTC().millis();
            if (timestamp.getCreateDate() == null) timestamp.setCreateDate(now);
            timestamp.setUpdateDate(now);
        }
    }
    
    private TimestampBE getTimestamp(HasTimestamp ht) {
        TimestampBE timestamp = ht.getTimestamp();
        if (timestamp == null) {
            timestamp = new TimestampBE();
            ht.setTimestamp(timestamp);
        }
        return timestamp;
    }
}</pre></div>



<h3 class="wp-block-heading">Reister the default listener</h3>



<p>Add the <code>src/main/resources/META-INF/orm.xml</code> and register the Listener above. Adjust the package as needed: </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;htmlmixed&quot;,&quot;mime&quot;:&quot;text/html&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;HTML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;html&quot;}">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;entity-mappings xmlns=&quot;http://java.sun.com/xml/ns/persistence/orm&quot;
                 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
                 xsi:schemaLocation=&quot;http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd&quot;
                 version=&quot;2.1&quot;&gt;
    &lt;persistence-unit-metadata&gt;
        &lt;persistence-unit-defaults&gt;
            &lt;entity-listeners&gt;
                &lt;entity-listener class=&quot;org.sterl.jpa.timestamp.TimestampEntityListener&quot; /&gt;
            &lt;/entity-listeners&gt;
        &lt;/persistence-unit-defaults&gt;
    &lt;/persistence-unit-metadata&gt;
&lt;/entity-mappings&gt;</pre></div>



<h3 class="wp-block-heading"> Use the new classes</h3>



<p>In the end, you may add the new class at any entity: </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror cm-s-eclipse" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Entity
@Data
@NoArgsConstructor @AllArgsConstructor @Builder
public class PersonBE implements HasTimestamp, Serializable {
    @Id 
    @GeneratedValue
    @Column(name = &quot;person_id&quot;)
    private Long id;
    private String name;
    @Embedded
    private TimestampBE timestamp;
}</pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2017/08/jpa-default-entity-listener/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
