<?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>Java crumbs &#187; Hibernate</title>
	<atom:link href="http://blog.krecan.net/category/hibernate/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.krecan.net</link>
	<description>Short remarks from Java world</description>
	<lastBuildDate>Tue, 27 Jul 2010 13:56:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hibernate SQL logging</title>
		<link>http://blog.krecan.net/2009/04/05/hibernate-sql-logging/</link>
		<comments>http://blog.krecan.net/2009/04/05/hibernate-sql-logging/#comments</comments>
		<pubDate>Sun, 05 Apr 2009 14:00:35 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Articles in English]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[SQl]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=345</guid>
		<description><![CDATA[If you need to log SQL queries generated by Hibernate together with parameter values you do not need P6Spy. It is enough to set-up log4j or your favorite logging framework like this

log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE

Then you will see everything in your log. For example:

7820 DEBUG [org.hibernate.SQL] {main} - insert into Client (name, personalNumber, id) values (?, ?, ?)
7821 [...]]]></description>
			<content:encoded><![CDATA[<p>If you need to log SQL queries generated by Hibernate together with parameter values you do not need <a href="http://www.p6spy.com/">P6Spy</a>. It is enough to set-up log4j or your favorite logging framework like this</p>
<p><code><br />
log4j.logger.org.hibernate.SQL=DEBUG<br />
log4j.logger.org.hibernate.type=TRACE<br />
</code></p>
<p>Then you will see everything in your log. For example:</p>
<p><code><br />
7820 DEBUG [org.hibernate.SQL] {main} - insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
7821 TRACE [org.hibernate.type.StringType] {main} - binding 'John Doe' to parameter: 1<br />
7821 TRACE [org.hibernate.type.StringType] {main} - binding '123X' to parameter: 2<br />
7821 TRACE [org.hibernate.type.LongType] {main} - binding '10' to parameter: 3<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/04/05/hibernate-sql-logging/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hibernate: přistupovat pomocí polí nebo vlastností?</title>
		<link>http://blog.krecan.net/2009/03/22/hibernate-pristupovat-pomoci-poli-nebo-vlastnosti/</link>
		<comments>http://blog.krecan.net/2009/03/22/hibernate-pristupovat-pomoci-poli-nebo-vlastnosti/#comments</comments>
		<pubDate>Sun, 22 Mar 2009 10:22:23 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[access]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=324</guid>
		<description><![CDATA[Onehdá jsem s kolegou řešil, jestli v Hibernate (JPA) používat přístup pomocí polí (field) nebo vlastností (property). Uvědomuji si, že nejsem ani první ani poslední kdo něco podobného řeší, nicméně mi došlo, že v tom sám nemám moc jasno tak jsem si dal za domácí úkol to nastudovat.
O co jde? Když mapuji entity, můžu si [...]]]></description>
			<content:encoded><![CDATA[<p>Onehdá jsem s kolegou řešil, jestli v Hibernate (JPA) používat přístup pomocí polí (field) nebo vlastností (property). Uvědomuji si, že nejsem ani první ani poslední kdo něco podobného řeší, nicméně mi došlo, že v tom sám nemám moc jasno tak jsem si dal za domácí úkol to nastudovat.</p>
<p>O co jde? Když mapuji entity, můžu si vybrat, jak bude Hibernate k objektům přistupovat. Mohu například  napsat takovouto třídu.</p>
<pre name="code" class="java">
@Entity
@Configurable
public class Client  {

	@Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
	private Long id;

	@Column(unique=true,nullable=false)
	private String personalNumber;

	...
}
</pre>
<p>V takovémto případě bude při načítání z databáze Hibernate data zapisovat přímo do polí. To znamená, že například pro ID nemusíme mít vůbec set metodu, Hibernate nebo jiný JPA poskytovatel to tam magicky zapíše.</p>
<p>Nebo mohu zvolit druhou variantu. </p>
<pre name="code" class="java">
@Entity
public class ClientGroup {

	private Long id;

	private List<Client> clients = new ArrayList<Client>();

	private String name;

	@Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
	public Long getId() {
		return id;
	}

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

	@OneToMany(cascade=CascadeType.ALL)
	public List<Client> getClients() {
		return clients;
	}

	private void setClients(List<Client> clients) {
		this.clients = clients;
	}
	public void addClient(Client client)
	{
		clients.add(client);
	}
	...
}
</pre>
<p>V tomto případě jsem dal anotace nad get metody a Hibernatu jsem tím dal najevo, že má pro přístup používat vlastnosti (property). Tzn. při plnění instancí z databáze bude volat set metody, při ukládání do databáze bude používat hodnoty z get metod.</p>
<p>Protože tu tvrdošíjně používám českou terminologii, shrnu to do slovníku.<br />
Field access – přístup pomocí polí – anotace nad poli<br />
Property access – přístup pomocí vlastností – anotace nad get metodami</p>
<p>Dobrá zpráva je, že v jednom programu mohu používat oba přístupy. Jednu třídu mohu mapovat tak, druhou onak. Sice bych to moc nedoporučoval, ale teoreticky to jde. U jednotlivých tříd ale oba přístupy míchat nemůžeme. Nemohu si říci, že ID chci mapovat jako field a seznam klientů jako property. Specifikaci už si nepamatuji, ale v praxi to funguje tak, že se typ přístupu určuje podle toho, nad co dám anotaci @Id. </p>
<p>Takže tu máme dva různé přístupy a nabízí se otázka, který je vhodnější. Oba mají svá pro a proti. Já osobně preferuji přístup přes pole. Prostě se smířím s tím, že mi Hibernate magicky mění vnitřnosti objektu. Podle některých to porušuje zapouzdření. Částečně mají tito lidé pravdu, ale tento přístup je podle mě menším ze dvou zel. Radši se smířím s tím, že mi zapouzdření bude narušovat Hibernate, než abych se smířil s tím, že mi ho bude narušovat programátor. </p>
<p>Vezměme si příklad ID. To je obvykle nastavováno Hibernatem. Rozhodně nechci, aby mi ho nastavoval nebo měnil programátor. V případě přístupu přes pole jednoduše nevytvořím set metodu a mám hotovo. V případě přístupu přes vlastnost musím vytvořit set metodu. Může být klidně i private, ale musí tam být. Takže stejně musím nechat Hibernate, aby mi prolomil zapouzdření. Stejně ho musím nechat volat private metodu. Nebo ji mohu nechat public, ale pak se musím modlit, aby mi někdo ID nezměnil. Mě osobně připadá čistší tam ten setter vůbec nedávat. </p>
<p>Podobný problém je i u kolekcí. Obvykle nechci nechat programátora, aby mi kolekci nastavoval přímo (viz. ClientGroup příklad). Ale u přístupu pomocí vlastností stejně musím mít set metodu, i když opět může být private.</p>
<p>Property přístup je podle mě také o trochu náchylnější na chybu. Představme si, že do objektu přidáme metodu getFullName, která jen zřetězí křestní jméno a příjmení. Když máme anotace nad poli, není tu žádný problém, pokud máme anotace nad metodami, tak si bude JPA myslet, že chceme mít v databázi sloupeček FULL_NAME a ošklivě nám vynadá. Budeme to muset vyřešit dobře mířenou anotací @Transient.</p>
<p>Specifickou kapitolou jsou netriviální get a set metody. V set metodách můžu mít validace vstupních hodnot, v get metodách vracet defenzivní kopie. U přístupu přes pole to není problém. Ale pokud používám přístup pomocí vlastností tak se mohou dít ošklivé věci. Validační kód se bude volat při každém načtení z databáze, což může mít na výkonnost dopad jen malý. Horší je to s defenzivními kopiemi. Ty mohou ovlivnit mechanismus detekce změn. Pokud budu například vracet defenzivní kopii kolekce, Hibernate bude přesvědčen, že se mu změnil obsah kolekce a pokaždé danou kolekci z databáze smaže a vloží ji tam znovu. A to i v situaci, že jsme danou instanci vůbec nezměnili! To může mít na výkonnost dopad dost ošklivý.</p>
<p>Teď mi zrovna došlo, v čem je problém. V podstatě obvykle potřebujeme, aby entita měla dvě rozhraní. Jedno pro programátory, druhé pro perzistenci. To je přesně to, co mi zajistí mapování přes pole.  Říkám tím, že ORM je taková chytřejší serializace po které chci aby mi uložila stav objektu. U klasické Java serializace si taky nikdo nestěžuje, že narušuje zapozdření tím, že nastavuje pole napřímo. Při přístupu přes vlastnosti na druhou stranu tvrdím, že ORM a programátor jsou si rovni a že by měli používat stejné rozhraní. Někdy to tak být může, ale obvykle tomu tak není.</p>
<p>Předchozí věta by tvořila pěkný závěr článku, naneštěstí ale ještě končit nemůžu. Je jeden konkrétní případ, kdy jsou anotace nad metodami lepší volba.  Je to v případě, že načítáme ID u lazy proxy, které ještě není načtené z databáze. Řekněme, že dělám například toto:</p>
<p><code>clientGroup.getClient(0).getId(</code>)</p>
<p>Může se stát, že Hibernate zná jenom ID klientů, kteří patří do dané skupiny, ale ještě nemá načtená jejich data. V tom případe se používá proxy, která zajistí načtení dat, až když jsou potřeba. Když používám přístup pomocí polí, Hibernate musí všechny informace o klientovi načíst, i když mě zajímá jen ID. Neví totiž, že metoda getId() jenom vrací klíč. Neví jestli náhodou v této metodě nečtu třeba jméno. Nemá šanci to poznat. Teoreticky by se mohl podívat do kódu, ale to by už bylo příliš mnoho magie. Na druhou stranu pokud mám nad metodou getId() anotaci @Id, Hibernate ví, že to je ID a může mi ho rovnou vrátit, aniž by musel přistupovat do databáze. </p>
<p>Ale toto je jediný případ, v kterém je přístup přes vlastnosti lepší. Záleží případ od případu, jestli zrovna tuto vlastnost použiji. Dovedu si představit aplikaci, kde budu například ID používat i v UI pro odkazy v tabulce. Dovoluji si ale tvrdit, že i tak by bylo lepší použít nějakou lepší fetch strategii než se prát s anotacemi nad metodami. Jinak to totiž zavání předčasnou optimalizací.</p>
<p>Další čtení:<br />
<a href="http://forum.hibernate.org/viewtopic.php?p=2349555&#038;sid=dd846f97d3eb352ed0b8fbe57739801c">http://forum.hibernate.org/viewtopic.php?p=2349555&#038;sid=dd846f97d3eb352ed0b8fbe57739801c</a></br><br />
<a href="http://chstath.blogspot.com/2007/05/field-access-vs-property-access-in-jpa.html">http://chstath.blogspot.com/2007/05/field-access-vs-property-access-in-jpa.html</a></br><br />
<a href="http://shashivelur.com/blog/2009/01/hibernate-direct-field-acess-and-encapsulation/">http://shashivelur.com/blog/2009/01/hibernate-direct-field-acess-and-encapsulation/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/03/22/hibernate-pristupovat-pomoci-poli-nebo-vlastnosti/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Spring managed Hibernate interceptor in JPA</title>
		<link>http://blog.krecan.net/2009/01/24/spring-managed-hibernate-interceptor-in-jpa/</link>
		<comments>http://blog.krecan.net/2009/01/24/spring-managed-hibernate-interceptor-in-jpa/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 16:29:27 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Articles in English]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[injection]]></category>
		<category><![CDATA[interceptor]]></category>
		<category><![CDATA[JPA]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=261</guid>
		<description><![CDATA[I have been trying to teach Hibernate injecting dependencies into Entities (I know, there is magic @Configurable annotation, I wanted to try it without magic). It is quite easy to do it using Hibernate interceptor (for example like this). But there is one drawback. It is not straightforward to inject interceptor into Hibernate when JPA [...]]]></description>
			<content:encoded><![CDATA[<p>I have been trying to teach Hibernate injecting dependencies into Entities (I know, there is magic <a href="http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-atconfigurable">@Configurable</a> annotation, I wanted to try it without magic). It is quite easy to do it using Hibernate interceptor (for example like <a href="https://java-crumbs.svn.sourceforge.net/svnroot/java-crumbs/jpa-test/tags/jpa-test-3.0/jpa-test/src/main/java/net/krecan/javacrumbs/jpa/interceptor/SpringInjectingInterceptor.java">this</a>). But there is one drawback. It is not straightforward to inject interceptor into Hibernate when JPA abstraction is in the way. </p>
<p>It is simple to define interceptor in <code>persistence.xml</code> using <a href="http://www.hibernate.org/hib_docs/entitymanager/reference/en/html/configuration.html#setup-configuration-bootstrapping">hibernate.ejb.interceptor</a> property. But it is only possible to specify class name, you can not inject Spring bean. If you read documentation to Spring <a href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html">LocalContainerEntityManagerFactoryBean</a> there is no possibility to specify the interceptor bean there neither. But there is a way how to achieve it. First of all, you have to redefine Hibernate PersistenceProvider. </p>
<pre name="code" class="java">
public class ConfigurableHibernatePersistence extends HibernatePersistence {
	private Interceptor interceptor;
	public Interceptor getInterceptor() {
		return interceptor;
	}

	public void setInterceptor(Interceptor interceptor) {
		this.interceptor = interceptor;
	}

	@SuppressWarnings("unchecked")
	@Override
	public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) {
		Ejb3Configuration cfg = new Ejb3Configuration();
		Ejb3Configuration configured = cfg.configure( info, map );
		postprocessConfiguration(info, map, configured);
		return configured != null ? configured.buildEntityManagerFactory() : null;
	}

	@SuppressWarnings("unchecked")
	protected void postprocessConfiguration(PersistenceUnitInfo info, Map map, Ejb3Configuration configured) {
		if (this.interceptor != null)
		{
			if (configured.getInterceptor()==null || EmptyInterceptor.class.equals(configured.getInterceptor().getClass()))
			{
				configured.setInterceptor(this.interceptor);
			}
			else
			{
				throw new IllegalStateException("Hibernate interceptor already set in persistence.xml ("+configured.getInterceptor()+")");
			}
		}
	}
}
</pre>
<p>(<a href="https://java-crumbs.svn.sourceforge.net/svnroot/java-crumbs/jpa-test/tags/jpa-test-3.0/jpa-test/src/main/java/net/krecan/javacrumbs/jpa/interceptor/ConfigurableHibernatePersistence.java">source</a>)</p>
<p>Here we override method <code>createContainerEntityManagerFactory</code> in order to add <code>postprocessConfiguration</code> method call. In this method, it is possible to change Hibernate configuration as needed. Now the only thing to be done is configuring Spring to use our new PersistenceProvider. It is quite simple.</p>
<pre name="code" class="xml">
	&lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
		&lt;property name="persistenceUnitName" value="testPU" /&gt;
		&lt;property name="dataSource" ref="dataSource" /&gt;
		&lt;property name="persistenceProvider"&gt;
			&lt;bean class="net.krecan.javacrumbs.jpa.interceptor.ConfigurableHibernatePersistence"&gt;
				&lt;property name="interceptor"&gt;
					&lt;bean class="net.krecan.javacrumbs.jpa.interceptor.SpringInjectingInterceptor"/&gt;
				&lt;/property&gt;
			&lt;/bean&gt;
		&lt;/property&gt;
	&lt;/bean&gt;
</pre>
<p>And that all folks, we have Spring configured interceptor even when using JPA abstraction. It would be better if similar classes were in Spring or Hibernate, but it's just few lines of code so feel free to copy them if you need to. If you know easier way how to do it, please mention it in the comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2009/01/24/spring-managed-hibernate-interceptor-in-jpa/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Spring factory method</title>
		<link>http://blog.krecan.net/2008/01/16/spring-factory-method/</link>
		<comments>http://blog.krecan.net/2008/01/16/spring-factory-method/#comments</comments>
		<pubDate>Wed, 16 Jan 2008 17:18:18 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Articles in English]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Hibernate statistics]]></category>
		<category><![CDATA[session factory]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/2008/01/16/spring-factory-method/</guid>
		<description><![CDATA[Today I am going to write about a small trick that I have used recently. Lets imagine following problem: we are using JPA (Hibernate) and Spring together.



&#60;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&#62;
	&#60;property name="persistenceUnitName" value="testPU" /&#62;
	&#60;property name="dataSource" ref="dataSource" /&#62;
	&#60;property name="jpaProperties"&#62;
		&#60;props&#62;
			&#60;prop key="hibernate.hbm2ddl.auto"&#62;${hibernate.hbm2ddl.auto}&#60;/prop&#62;
		&#60;/props&#62;
	&#60;/property&#62;
&#60;/bean&#62;



It works nice, without any problem. But imagine that one day you need to access Hibernate statistics. To achieve [...]]]></description>
			<content:encoded><![CDATA[<p>Today I am going to write about a small trick that I have used recently. Lets imagine following problem: we are using JPA (Hibernate) and Spring together.</p>
<div  class="xml">
<pre>
<code>
&lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
	&lt;property name="persistenceUnitName" value="testPU" /&gt;
	&lt;property name="dataSource" ref="dataSource" /&gt;
	&lt;property name="jpaProperties"&gt;
		&lt;props&gt;
			&lt;prop key="hibernate.hbm2ddl.auto"&gt;${hibernate.hbm2ddl.auto}&lt;/prop&gt;
		&lt;/props&gt;
	&lt;/property&gt;
&lt;/bean&gt;
</code>
</pre>
</div>
<p>It works nice, without any problem. But imagine that one day you need to access <a href="http://www.javalobby.org/java/forums/t19807.html">Hibernate statistics</a>. To achieve this, you have to have access to the Hibernate session factory. But we have no session factory here, we are using the entity manager which hides session factory underneath. How to access it? The solution is simple, you can use factory method. </p>
<div  class="xml">
<pre>
<code>
&lt;!-- Publishing session factory to be able view statistics --&gt;
&lt;bean id="sessionFactory" factory-bean="entityManagerFactory" factory-method="getSessionFactory" /&gt;
</code>
</pre>
</div>
<p>By this simple code we say to Spring: Hey, just call the method getSessionFactory on the entityManagerFactory bean and store the result as a bean with name sessionFactory.  Since we are using Hibernate as the JPA provider, entityManagerFactory is instance of <a href="http://www.hibernate.org/hib_docs/entitymanager/api/org/hibernate/ejb/HibernateEntityManagerFactory.html">HibernateEntityManagerFactory</a> and by a chance it has  getSessionFactory method. Now we have access to the session factory and we can use it however we like.</p>
<p><em>Note: If you wonder why the hell I have started to write in something that looks almost like English when apparently I do even more mistakes than in Czech, the answer is simple. I just need to practice my English (apart from that I want to be world famous, not just known in Czech Republic)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2008/01/16/spring-factory-method/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flushing Hibernate</title>
		<link>http://blog.krecan.net/2008/01/05/flushing-hibernate/</link>
		<comments>http://blog.krecan.net/2008/01/05/flushing-hibernate/#comments</comments>
		<pubDate>Sat, 05 Jan 2008 12:58:27 +0000</pubDate>
		<dc:creator>Lukáš Křečan</dc:creator>
				<category><![CDATA[Articles in English]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[DML]]></category>
		<category><![CDATA[flush]]></category>
		<category><![CDATA[order]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/2008/01/05/flushing-hibernate/</guid>
		<description><![CDATA[Today I am going to write about Hibernate flushing. Do not worry, I am not going to flush Hibernate to the toilet. I will write about the way, how Hibernate propagates changes to the database. 
When you are modifying data using Hibernate, you have to keep in mind that Hibernate uses so called write-behind. It [...]]]></description>
			<content:encoded><![CDATA[<p>Today I am going to write about Hibernate flushing. Do not worry, I am not going to flush Hibernate to the toilet. I will write about the way, how Hibernate propagates changes to the database. </p>
<p>When you are modifying data using Hibernate, you have to keep in mind that Hibernate uses so called write-behind. It means that Hibernate propagates changes to the database as late as possible. By default this propagation (flushing) happens at the following times</p>
<ul>
<li>when transaction is committed</li>
<li>before query is executed</li>
<li>when  flush() method is called explicitly</li>
</ul>
<p>Usually such behavior is a good thing. It enables Hibernate to optimize data modifications and allows grouping many changes to one big batch update. But sometimes you can encounter some interesting issues. Lets show it on some example. Lets have following entity class:</p>
<div align="left" class="java">
<table border="0" cellpadding="3" cellspacing="0" bgcolor="#ffffff">
<tr>
  <!-- start source code --></p>
<td nowrap="nowrap" valign="top" align="left">
    <code><br />
<font color="#808080">01</font>&nbsp;<font color="#646464">@Entity</font><br />
<font color="#808080">02</font>&nbsp;<font color="#7f0055"><b>public&nbsp;class&nbsp;</b></font><font color="#000000">Client&nbsp;&nbsp;</font><font color="#000000">{</font><br />
<font color="#808080">03</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><br />
<font color="#808080">04</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#646464">@Id&nbsp;@GeneratedValue</font><font color="#000000">(</font><font color="#000000">strategy=GenerationType.AUTO</font><font color="#000000">)</font><br />
<font color="#808080">05</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>private&nbsp;</b></font><font color="#000000">Long&nbsp;id;</font><br />
<font color="#808080">06</font>&nbsp;<font color="#ffffff"></font><br />
<font color="#808080">07</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#646464">@Column</font><font color="#000000">(</font><font color="#000000">unique=true,nullable=</font><font color="#7f0055"><b>false</b></font><font color="#000000">)</font><br />
<font color="#808080">08</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>private&nbsp;</b></font><font color="#000000">String&nbsp;personalNumber;</font><br />
<font color="#808080">09</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><br />
<font color="#808080">10</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#646464">@Column</font><br />
<font color="#808080">11</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>private&nbsp;</b></font><font color="#000000">String&nbsp;name;</font><br />
<font color="#808080">12</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><br />
<font color="#808080">13</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">.</font><br />
<font color="#808080">13</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">.</font><br />
<font color="#808080">13</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">.</font><br />
<font color="#808080">14</font>&nbsp;<font color="#000000">}</font></code></p>
</td>
<p>  <!-- end source code --><br />
   </tr>
</table>
</div>
<p>We see that a client has id which is used internally as an identifier. Moreover a client has a personal number which we are using as a business key. Then he has some other attributes as name. Notice that the personal number is obligatory and it has to be unique.</p>
<p>We can test flushing by the following code, using <a href="https://java-crumbs.svn.sourceforge.net/svnroot/java-crumbs/jpa-test/tags/jpa-test-2.0/src/main/java/net/krecan/javacrumbs/jpatest/dao/jpa/JpaClientDao.java">ClinetDao</a>:</p>
<div align="left" class="java">
<table border="0" cellpadding="3" cellspacing="0" bgcolor="#ffffff">
<tr>
  <!-- start source code --></p>
<td nowrap="nowrap" valign="top" align="left">
    <code><br />
<font color="#808080">01</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Client&nbsp;client&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Client</font><font color="#000000">(</font><font color="#000000">PERSONAL_NUM</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">02</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Creating&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">03</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">clientDao.createClient</font><font color="#000000">(</font><font color="#000000">client</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">04</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">05</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Changing&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">06</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">client.setName</font><font color="#000000">(</font><font color="#2a00ff">&#34;Carl&nbsp;von&nbsp;Bahnhof&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">07</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">08</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Deleting&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">09</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">clientDao.deleteClient</font><font color="#000000">(</font><font color="#000000">client.getId</font><font color="#000000">())</font><font color="#000000">;</font><br />
<font color="#808080">10</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">11</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Trying&nbsp;to&nbsp;load&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">12</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">assertNull</font><font color="#000000">(</font><font color="#000000">clientDao.loadClientWithPersonalNumberOrReturnNull</font><font color="#000000">(</font><font color="#000000">PERSONAL_NUM</font><font color="#000000">))</font><font color="#000000">;</font><br />
<font color="#808080">13</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">14</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Creating&nbsp;second&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">15</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">clientDao.createClient</font><font color="#000000">(</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Client</font><font color="#000000">(</font><font color="#000000">PERSONAL_NUM</font><font color="#000000">))</font><font color="#000000">;</font></code></p>
</td>
<p>  <!-- end source code --><br />
   </tr>
</table>
</div>
<p>When it is executed on HSQLDB we get following output (we see my logging messages mixed with Hibernate SQL output).</p>
<div class="code">
<code><br />
Creating first client<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
call identity()<br />
Changing first client<br />
Deleting first client<br />
Trying to load first client<br />
delete from Client where id=?<br />
select client0_.id as id2_, client0_.name as name2_, client0_.personalNumber as personal3_2_ from Client client0_ where client0_.personalNumber=?<br />
Creating second client<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
call identity()<br />
</code>
</div>
<p>We see that inserts are called at once. They are not postponed until flush. In this case, Hibernate has to call insert at once because it has to get the client id from the database. (remember all non-transient entities have to have id) So inserts can not wait until flush, they have to be executed directly. In order to make our example more clear, we can change id generation strategy to sequence. </p>
<div align="left" class="java">
<table border="0" cellpadding="3" cellspacing="0" bgcolor="#ffffff">
<tr>
  <!-- start source code --></p>
<td nowrap="nowrap" valign="top" align="left">
    <code><br />
<font color="#808080">01</font>&nbsp;<font color="#646464">@Entity</font><br />
<font color="#808080">02</font>&nbsp;<font color="#7f0055"><b>public&nbsp;class&nbsp;</b></font><font color="#000000">Client&nbsp;&nbsp;</font><font color="#000000">{</font><br />
<font color="#808080">03</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><br />
<font color="#808080">04</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#646464">@Id&nbsp;@GeneratedValue</font><font color="#000000">(</font><font color="#000000">strategy=GenerationType.SEQUENCE</font><font color="#000000">)</font><br />
<font color="#808080">05</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>private&nbsp;</b></font><font color="#000000">Long&nbsp;id;</font><br />
<font color="#808080">06</font>&nbsp;<font color="#ffffff"></font><br />
<font color="#808080">07</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#646464">@Column</font><font color="#000000">(</font><font color="#000000">unique=true,nullable=</font><font color="#7f0055"><b>false</b></font><font color="#000000">)</font><br />
<font color="#808080">08</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>private&nbsp;</b></font><font color="#000000">String&nbsp;personalNumber;</font><br />
<font color="#808080">09</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><br />
<font color="#808080">10</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#646464">@Column</font><br />
<font color="#808080">11</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>private&nbsp;</b></font><font color="#000000">String&nbsp;name;</font><br />
<font color="#808080">12</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><br />
<font color="#808080">13</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">.</font><br />
<font color="#808080">14</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">.</font><br />
<font color="#808080">15</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">.</font><br />
<font color="#808080">16</font>&nbsp;<font color="#000000">}</font></code></p>
</td>
<p>  <!-- end source code --><br />
   </tr>
</table>
</div>
<p>To get the client id, insert is not needed any more. It can be postponed until flush and we get following output</p>
<div class="code">
<code>Creating first client<br />
select next value for hibernate_sequence from dual_hibernate_sequence<br />
Changing first client<br />
Deleting first client<br />
Trying to load first client<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
delete from Client where id=?<br />
select client0_.id as id2_, client0_.name as name2_, client0_.personalNumber as personal3_2_ from Client client0_ where client0_.personalNumber=?<br />
Creating second client<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)</code>
</div>
<p>As you can see creation of the first client and his deletion is realized just before the select statement.  Changes have to be propagated to the DB so the select statement has access to changed data. You can notice, that there is no update, change of the name was already included into the insert statement. So far so good. Where is the problem? Lets comment out the query (You do not have to comment it out, in the real world it can be bypassed by the second-level cache).</p>
<div align="left" class="java">
<table border="0" cellpadding="3" cellspacing="0" bgcolor="#ffffff">
<tr>
  <!-- start source code --></p>
<td nowrap="nowrap" valign="top" align="left">
    <code><br />
<font color="#808080">01</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Client&nbsp;client&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Client</font><font color="#000000">(</font><font color="#000000">PERSONAL_NUM</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">02</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Creating&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">03</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">clientDao.createClient</font><font color="#000000">(</font><font color="#000000">client</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">04</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">05</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Changing&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">06</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">client.setName</font><font color="#000000">(</font><font color="#2a00ff">&#34;Carl&nbsp;von&nbsp;Bahnhof&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">07</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">08</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Deleting&nbsp;first&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">09</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">clientDao.deleteClient</font><font color="#000000">(</font><font color="#000000">client.getId</font><font color="#000000">())</font><font color="#000000">;</font><br />
<font color="#808080">10</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">11</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#3f7f5f">//LOG.debug(&#34;Trying&nbsp;to&nbsp;load&nbsp;first&nbsp;client&#34;);</font><br />
<font color="#808080">12</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#3f7f5f">//assertNull(clientDao.loadClientWithPersonalNumberOrReturnNull(PERSONAL_NUM));</font><br />
<font color="#808080">13</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><br />
<font color="#808080">14</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">LOG.debug</font><font color="#000000">(</font><font color="#2a00ff">&#34;Creating&nbsp;second&nbsp;client&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#808080">15</font>&nbsp;<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">clientDao.createClient</font><font color="#000000">(</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Client</font><font color="#000000">(</font><font color="#000000">PERSONAL_NUM</font><font color="#000000">))</font><font color="#000000">;</font></code></p>
</td>
<p>  <!-- end source code --><br />
   </tr>
</table>
</div>
<p>We get following output</p>
<div class="code">
<code>Creating first client<br />
select next value for hibernate_sequence from dual_hibernate_sequence<br />
Changing first client<br />
Deleting first client<br />
Creating second client<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
SQL Error: 0, SQLState: null<br />
failed batch<br />
Could not synchronize database state with session<br />
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update<br />
	at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)<br />
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)<br />
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)<br />
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)<br />
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)<br />
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)<br />
	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)<br />
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)<br />
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)<br />
	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)<br />
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)<br />
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)<br />
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:438)<br />
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:662)<br />
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632)<br />
	at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:346)<br />
	at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:199)<br />
	at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:340)<br />
	at org.springframework.test.context.junit4.SpringMethodRoadie.runAfters(SpringMethodRoadie.java:351)<br />
	at org.springframework.test.context.junit4.SpringMethodRoadie.runBeforesThenTestThenAfters(SpringMethodRoadie.java:262)<br />
	at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:234)<br />
	at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:204)<br />
	at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:146)<br />
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:151)<br />
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)<br />
	at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)<br />
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)<br />
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)<br />
	at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)<br />
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)<br />
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)<br />
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)<br />
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)<br />
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)<br />
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)<br />
Caused by: java.sql.BatchUpdateException: failed batch<br />
	at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)<br />
	at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)<br />
	at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)<br />
	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)<br />
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)<br />
	... 31 more</code>
</div>
<p>Wow.  It looks like Hibernate is trying to insert both clients with the same personal number without deleting the first one. Lets try to remove uniqueness condition from the client and take a look at the output:</p>
<div class="code">
<code>Creating first client<br />
select next value for hibernate_sequence from dual_hibernate_sequence<br />
Changing first client<br />
Deleting first client<br />
Creating second client<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
insert into Client (name, personalNumber, id) values (?, ?, ?)<br />
delete from Client where id=?</code>
</div>
<p>Yes, Hibernate changed order of the commands! Without the unique constraint it does not matter, final result is the same. But with the constraint enabled, we can not use our code any more. Is it a bug? No, it is a feature. If you dig deep into the Hibernate source code, you will find following <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/event/def/AbstractFlushingEventListener.html#performExecutions(org.hibernate.event.EventSource)">comment </a></p>
<blockquote><p>Execute all SQL and second-level cache updates, in a<br />
	 special order so that foreign-key constraints cannot<br />
	 be violated:</p>
<ol>
<li> Inserts, in the order they were performed
<li> Updates
<li> Deletion of collection elements
<li> Insertion of collection elements
<li> Deletes, in the order they were performed
	 </ol>
</blockquote>
<p>And that is exactly our case. When flushing, Hibernate executes all inserts before delete statements. </p>
<p>So if we need to run our example, we have to force Hibernate to flush the delete before the second insert. The best way is to call entityManager.flush() explicitly just after the delete.  </p>
<p>To reiterate, Hibernate is using write-behind. All data manipulating statements are executed as late as possible. One exception are insert statements. Sometimes Hibernate needs to call insert in order to get the ID of the entity. The important point is, that <strong>order of the commands can be changed by Hibernate</strong>. Usually it does not matter, since transactions are atomic. But sometimes we can encounter interesting issues. Especially when using database constraints.</p>
<p><em>The source code can be downloaded from <a href="https://java-crumbs.svn.sourceforge.net/svnroot/java-crumbs/jpa-test/tags/jpa-test-2.0">SVN repository</a>.</em></p>
<p><em>Note: If you wonder why the hell I have started to write in something that looks almost like English when apparently I do even more mistakes than in Czech, the answer is simple. I just need to practice my English (apart from that I want to be world famous, not just known in Czech Republic)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2008/01/05/flushing-hibernate/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Nedostatky JPA</title>
		<link>http://blog.krecan.net/2007/02/25/nedostatky-jpa/</link>
		<comments>http://blog.krecan.net/2007/02/25/nedostatky-jpa/#comments</comments>
		<pubDate>Sun, 25 Feb 2007 09:27:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/2007/02/25/nedostatky-jpa/</guid>
		<description><![CDATA[Nenechte se zmást názvem, myslím si, že JPA je dobrý a užitečný standard. Nicméně je nutné mít na mysli, že je to jenom standard, tudíž s sebou nese všechny klady i nedostatky, které jsou se standardy obvykle spojeny.
JPA vznikalo v situaci, kdy bylo na trhu několik dodavatelů O/R mapovacích nástrojů. Mnozí z nich se i [...]]]></description>
			<content:encoded><![CDATA[<p>Nenechte se zmást názvem, myslím si, že JPA je dobrý a užitečný standard. Nicméně je nutné mít na mysli, že je to jenom standard, tudíž s sebou nese všechny klady i <a href="http://www.sweb.cz/pichlik/archive/2006_09_17_archive.html" title="Problémy standardů - když méně je vlastně více">nedostatky, které jsou se standardy obvykle spojeny</a>.</p>
<p>JPA vznikalo v situaci, kdy bylo na trhu několik dodavatelů O/R mapovacích nástrojů. Mnozí z nich se i na jeho vývoji podíleli. Nemůže nás proto překvapovat, že JPA pokrývá jenom podmnožinu průniku funkčností, které existující nástroje umožňovaly. To co uměl například Hiberante oproti Toplinku se do standardu prostě dostat nemohlo. Platí to samozřejmě i naopak. V tomto článku, bych chtěl shrnout pár věcí, které mi v JPA chybí.</p>
<h3>Vlastní typy (UserTypes , Custom types)</h3>
<p>JPA umožňuje ukládat jenom následující typy:</p>
<blockquote><p>Java primitive types; java.lang.String; other Java serializable types (including wrappers of the primitive types, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, user-defined serializable types, byte[], Byte[], char[], and Character[]); enums; entity types and/or collections of entity types; and embeddable classes</p></blockquote>
<p>Na první pohled by se mohlo stát, že to stačí. Nicméně co dělat, když máme například položku typu java.net.URL a chceme ji uložit jako String? Pomocí JPA se vám ji podaří uložit jedině v serializované podobě. Zajímavou <a href="http://www.theserverside.com/news/thread.tss?thread_id=41886">diskuzi k tomuto tématu najdete na TSS</a>.</p>
<p><a href="http://www.theserverside.com/news/thread.tss?thread_id=41886" title="Diskuze na TSS"><br />
</a></p>
<h3>Criteria API</h3>
<p><a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Criteria.html">Criteria API</a> je funkčnost Hibernate, které se hodí, když skládáme databázový dotaz za běhu. Například, pokud máme formulář pro uživatelsky definovaný filtr. Bez criteria API musíme skládat dotaz do řetězce jen proto, aby si ho mohl JPA provider vzápětí naparsovat a složit z něj SQL řetězec. To se mi zdá trochu postavené na hlavu.</p>
<p><a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Criteria.html" title="Criteria API"><br />
</a></p>
<h3>Jednosměrné one-to-many vztahy bez join tabulky</h3>
<p>Více na jednom z <a href="http://blog.krecan.net/2006/11/01/hibernate-a-jednosmerne-one-to-many-vztahy/">předchozích příspěvků</a>. Například Toplink Essentials tyto vazby opravdu nepodporuje.</p>
<h3>Zabíjení sirotečků (delete-orphan)</h3>
<p>Umožňuje nám automaticky mazat prvky, které jsme odebrali z one-to-many asociace. Mám-li například třídu klient, která obsahuje kolekci adres, delete orphan mi zajistí automatické smazání adresy poté, co ji odeberu z kolekce. Jelikož JPA tuto funkcionalitu nepodporuji, je nutné adresy mazat ručně, což v některých situacích může být dost komplikované. Více se můžete dočíst v <a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html#objectstate-transitive">dokumentaci k Hibernate</a>.</p>
<p><a href="http://blog.krecan.net/2006/11/01/hibernate-a-jednosmerne-one-to-many-vztahy/"><br />
</a></p>
<h3>Nastavení pro ladění výkonu</h3>
<p>Například <a href="http://blog.krecan.net/2006/10/24/hibernate-a-paralelni-kolekce/">BatchSize</a> a další. Ladění výkonu je věc, na kterou obvykle v aplikacích typu HalloWord nenarazíte. Pokud ovšem budete psát reálnou aplikaci, bez těchto funkcionalit se neobejdete. A JPA vám kromě možnosti psaní si vlastního SQL mnoho pomoci nenabídne.</p>
<p>Další věci, které nejsou pokryty standardem, ale například Hibernate je umožňuje, můžeme najít na  v dokumentaci k <a href="http://www.hibernate.org/hib_docs/annotations/reference/en/html_single/#entity-hibspec">Hibernate Extensions</a>.</p>
<p>A co nám z toho plyne? JPA udělalo velikou práci v tom, že sjednotilo metadata pro O/R mapování. Pokud vám nevadí psaní metadat v anotacích, určitě je dobré tento standard používat. Zajistíte si tím snazší přenositelnost na jiného JPA providera. Je ale nepravděpodobné, že se vám podaří napsat a provozovat aplikaci čistě v JPA, aniž by byla závislá na konkrétní implementaci. Pokud se tedy vzdáme iluze o snadné přenositelnosti, je podle mého názoru nejrozumnější používat JPA jenom na definici metadat. Pro DAO vrstvu bych už používal implementaci, na kterou už jsme tak jako tak vázáni. Tzn. v případě Hibernate by to byl Springovský <a href="http://www.springframework.org/docs/api/org/springframework/orm/hibernate/HibernateTemplate.html">HibernateTemplate</a>, který mi umožní používat HQL a Criteria API.</p>
<p>A to je právě to krásné na JPA, nenutí mě brát všechno nebo nic. Dává mi svobodu vybrat si jak moc ho chci používat. Mohu si vybrat jestli ho chci „degradovat“ jen na formu zápisu metadat nebo jestli mi jeho omezení stojí za tu iluzi snadné přenositelnosti.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2007/02/25/nedostatky-jpa/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hibernate a jednosměrné one-to-many vztahy</title>
		<link>http://blog.krecan.net/2006/11/01/hibernate-a-jednosmerne-one-to-many-vztahy/</link>
		<comments>http://blog.krecan.net/2006/11/01/hibernate-a-jednosmerne-one-to-many-vztahy/#comments</comments>
		<pubDate>Wed, 01 Nov 2006 19:39:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Hibernate]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=11</guid>
		<description><![CDATA[Dnes nebudu psát nic světoborného. Jen bych uvedl na pravou míru chybu, které jsem se dopustil v minulém článku. Není pravda, že Hibernate neumí jednosměrné one-to-many vztahy bez použití join tabulky, naopak je to docela snadné.
Na svoji obhajobu mohu uvést jen to, že jsem to v době psaní článku moc neřešil a narazil jsem na [...]]]></description>
			<content:encoded><![CDATA[<p>Dnes nebudu psát nic světoborného. Jen bych uvedl na pravou míru chybu, které jsem se dopustil v minulém článku. Není pravda, že Hibernate neumí jednosměrné one-to-many vztahy bez použití join tabulky, naopak je to docela snadné.</p>
<p>Na svoji obhajobu mohu uvést jen to, že jsem to v době psaní článku moc neřešil a narazil jsem na dokumentaci, která naznačovala, že to není nijak moc jednoduché. A hlavně, abych nevypadal jako úplný blbec, ponořil jsem se do specifikace EJB 3.0. Tam jsem na straně 185 našel následující text</p>
<blockquote><p>Unidirectional one-to-many relationships may be implemented using one-to-many foreign key mappings, however, such support is not required in this release. Applications that want to use a foreign key mapping strategy for one-to-many relationships should make these relationships bidirectional to ensure portability.</p></blockquote>
<p>Takže se mohu vymlouvat, že jsem tu relaci udělal obousměrnou, abych zařídil přenositelnost.</p>
<p>Ale dost už bylo výmluv, podívejme se na to jak ono mapování zařídit. Připomenu jen, že vytváříme třídu Client, která obsahuje kolekci adres a účtů (viz. obrázek)</p>
<p><a href="http://bimbo.fjfi.cvut.cz/%7Ekrecan/blog/er.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://bimbo.fjfi.cvut.cz/%7Ekrecan/blog/er.png" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px" border="0" /></a></p>
<pre>
<p class="java" align="left">
<table style="color: #ffffff" border="0" cellpadding="3" cellspacing="0">
<tbody>
<tr>
<td align="left" nowrap="nowrap" valign="top"><code></code></td>

<!-- end source code --></tr>
</tbody>
</table>

<!-- start source code --></pre>
<table style="color: #ffffff" border="0" cellpadding="3" cellspacing="0">
<tr>
<td align="left" nowrap="nowrap" valign="top"><code><font style="color: #646464">@Entity</font><br />
<font style="color: #646464">@Table</font><font style="color: #000000">(</font><font style="color: #000000">name=</font><font style="color: #2a00ff">"client"</font><font style="color: #000000">)</font><br />
<font style="color: #7f0055"><strong>public class </strong></font><font style="color: #000000">Client  </font><font style="color: #000000">{</font><br />
<font style="color: #ffffff"> </font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@Id @GeneratedValue</font><font style="color: #000000">(</font><font style="color: #000000">strategy=GenerationType.AUTO</font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #7f0055"><strong>private </strong></font><font style="color: #000000">Integer id;</font></code><font style="color: #ffffff">  </font><font style="color: #646464">@Column</font><br />
<font style="color: #ffffff">  </font><font style="color: #7f0055"><strong>private </strong></font><font style="color: #000000">Long personId;</font><br />
<font style="color: #ffffff">  </font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@Column</font><br />
<font style="color: #ffffff">  </font><font style="color: #7f0055"><strong>private </strong></font><font style="color: #000000">String name;</font><br />
<font style="color: #ffffff"> </font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@OneToMany</font><font style="color: #000000">(</font><font style="color: #000000">cascade=CascadeType.ALL</font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@JoinColumn</font><font style="color: #000000">(</font><font style="color: #000000">name=</font><font style="color: #2a00ff">"client_id"</font><font style="color: #000000">, nullable=</font><font style="color: #7f0055"><strong>false</strong></font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@BatchSize</font><font style="color: #000000">(</font><font style="color: #000000">size=</font><font style="color: #990000">10</font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #7f0055"><strong>private </strong></font><font style="color: #000000">Set&lt;Account&gt; accounts = </font><font style="color: #7f0055"><strong>new </strong></font><font style="color: #000000">HashSet&lt;Account&gt;</font><font style="color: #000000">()</font><font style="color: #000000">;</font><br />
<font style="color: #ffffff"> </font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@OneToMany</font><font style="color: #000000">(</font><font style="color: #000000">cascade=CascadeType.ALL</font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@JoinColumn</font><font style="color: #000000">(</font><font style="color: #000000">name=</font><font style="color: #2a00ff">"client_id"</font><font style="color: #000000">, nullable=</font><font style="color: #7f0055"><strong>false</strong></font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #646464">@BatchSize</font><font style="color: #000000">(</font><font style="color: #000000">size=</font><font style="color: #990000">10</font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #7f0055"><strong>private </strong></font><font style="color: #000000">Set&lt;Address&gt; addresses = </font><font style="color: #7f0055"><strong>new </strong></font><font style="color: #000000">HashSet&lt;Address&gt;</font><font style="color: #000000">()</font><font style="color: #000000">;</font><br />
<font style="color: #ffffff"> </font><font style="color: #ffffff">  </font><br />
<font style="color: #ffffff">  </font><font style="color: #ffffff">  </font><font style="color: #7f0055"><strong>public </strong></font><font style="color: #7f0055"><strong>void </strong></font><font style="color: #000000">addAddress</font><font style="color: #000000">(</font><font style="color: #000000">Address address</font><font style="color: #000000">)</font><br />
<font style="color: #ffffff">  </font><font style="color: #000000">{</font><br />
<font style="color: #000000">  addresses.add</font><font style="color: #000000">(</font><font style="color: #000000">address</font><font style="color: #000000">)</font><font style="color: #000000">;</font><br />
<font style="color: #ffffff">  </font><font style="color: #000000">}<br />
//zbytek vynechán<br />
}</font></td>
</tr>
</table>
<p>Všimněte si prosím anotace <font face="courier new">@JoinColumn(name="client_id", nullable=false)</font>, která nám zajistí požadované mapovaní přes cizí klíč. Důležitý je druhý atribut - nullable. Ten Hibernatu říká, že cizí klíč <font face="courier new">client_id</font> v tabulce <font face="courier new">address </font>nesmí obsahovat null.</p>
<p>Oproti minulé verzi vidíme značné zjednodušení. Nemusíme se starat o plnění druhého směru relace. Dokonce ani neuděláme stejnou chybu jako já minule, když jsem zapomněl vyřešit předávání adresy mezi klienty (automatické odebrání adresy jednomu klientovi, při přidání druhému). Abych to ještě více zjednodušil, použil jsem přehlednější, i když méně výkonnou, formu inicializace množiny adres.</p>
<p>Takže pro shrnutí, jednosměrná one-to-many relace v Hibernate funguje, nicméně není přenositelná v rámci EJB 3.0. Ještě bych chtěl na závěr poděkovat Markovi L. za to, že mě upozornil na spoustu chyb v minulém článku a ukázal mi, že by to mapování měl Hibernate přeci jenom umět.</p>
<p>Zdrojové kódy můžete stáhnout <a href="http://blog.krecan.net/files/hibernate-test-2006-11-01.zip">zde</a>.</p>
<p>Zdroje:</p>
<ol>
<li>JSR 220: Enterprise JavaBeansTM,Version 3.0</li>
<li><a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/collections.html#collections-onetomany">Hibernate dokumentace<br />
</a></li>
<li><a href="http://chris-richardson.blog-city.com/ejb_30__still_trying_to_catch_up_to_jdo_and_hibernate.htm">EJB 3.0 – still trying to catch up to JDO and Hibernate</a></li>
<li><a href="http://www.cs.bham.ac.uk/%7Eaps/syllabi/2004_2005/issws/h03/hibernate.html#one_to_many_unidir">Getting Started with Hibernate</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2006/11/01/hibernate-a-jednosmerne-one-to-many-vztahy/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hibernate a paralelní kolekce</title>
		<link>http://blog.krecan.net/2006/10/24/hibernate-a-paralelni-kolekce/</link>
		<comments>http://blog.krecan.net/2006/10/24/hibernate-a-paralelni-kolekce/#comments</comments>
		<pubDate>Tue, 24 Oct 2006 19:38:32 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Hibernate]]></category>

		<guid isPermaLink="false">http://blog.krecan.net/?p=10</guid>
		<description><![CDATA[Napsal jsem menší článek o tom jak poladit výkonost dotazů v Hibernate. Jelikož se mi ho nepodařilo převést do HTML, můžete si ho přečíst v PDF.
]]></description>
			<content:encoded><![CDATA[<p>Napsal jsem menší článek o tom jak poladit výkonost dotazů v Hibernate. Jelikož se mi ho nepodařilo převést do HTML, můžete si ho přečíst v <a href="http://www.krecan.net/blog/hibernate1.pdf">PDF</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.krecan.net/2006/10/24/hibernate-a-paralelni-kolekce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
