ShredzoneShred's Bloghttps://shred.zone/tag-Hibernate2018-07-17T20:32:35Z2018-07-17T20:32:35ZHibernate 4 schema generation with MavenShredhttps://shred.zone/author-1https://shred.zone/page-3812018-07-17T18:05:19Z2014-08-31T23:23:44Z<p>While upgrading my blog software <a href="https://cilla.shredzone.org" class="exts">Cilla</a> to Java 8 and Hibernate 4, I found out that the old <code>hibernate3-maven-plugin</code> refused to create <code>schema.sql</code> files. Well, it wasn't really surprising. The name of the plugin already implied that the plugin won't play with the next major release of Hibernate.</p>
<p>I could not spot an official update of the plugin. Instead, I found <em>Kai Moritz</em> <a href="https://juplo.de/hibernate4-maven-plugin/" class="exts">new Hibernate 4 maven plugin</a>, which turned out to be very useful.</p>
<p>One key feature is to set up and initialize a local database for unit testing. I don't need this feature for Cilla (yet 😉). All I need is a <code>hbm2ddl</code> style generation of a SQL schema file for setting up new instances of my blog software from scratch. It turned out that the plugin was easily configured that way, and so it got almost a drop-in replacement for the old plugin.</p>
<p>This is what the <code><plugins></code> section of the project's pom file looks like:</p>
<pre class="prettyprint"><code class="language-xml"><plugin>
<groupId>de.juplo</groupId>
<artifactId>hibernate4-maven-plugin</artifactId>
<version>1.0.4</version>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
<configuration>
<hibernateDialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernateDialect>
<target>NONE</target>
<type>CREATE</type>
</configuration>
</plugin>
</code></pre>
<p>With the <code>target</code> set to <code>NONE</code>, the <code>schema.sql</code> file is quietly generated while building the project. If set to <code>SCRIPT</code>, a copy will be dumped to stdout.</p>
<p>A <code>CREATE</code> <code>type</code> only generates create statements of the database. The default is <code>BOTH</code>, which creates drop and create statements.</p>
<p>Since no actual database is created, there is no need to add <code>user</code>, <code>password</code> and <code>url</code> parameters.</p>
<p>A list of all configuration options can be found <a href="https://juplo.de/hibernate4-maven-plugin/export-mojo.html" class="exts">here</a>. The plugin is available at <a href="https://search.maven.org/" class="exts">Maven Central</a>.</p>2014-08-31T23:23:44Zhibernate3-maven-plugin fails with Java 1.7Shredhttps://shred.zone/author-1https://shred.zone/page-3522018-07-17T20:20:26Z2012-01-24T00:05:32Z<p>If you're using Maven's <code>hibernate3-maven-plugin</code> for creating a DDL file from your entities, you might encounter the following error when using Java 1.7:</p>
<pre>
Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed:
An AnnotationConfiguration instance is required
</pre>
<p>The reason seems to be a broken JRE detection in the Mojo code, which mistakenly assumes that Java 1.7 does not support annotations. However, I haven't checked that in depth.</p>
<p>The fix is pretty easy. In the plugin configuration of the <code>hibernate3-maven-plugin</code>, add an <code>implementation</code> property to the <code>componentProperties</code> like this:</p>
<pre class="prettyprint"><code class="language-xml"><plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<componentProperties>
<implementation>annotationconfiguration</implementation>
</componentProperties>
</configuration>
</plugin>
</code></pre>
<p>This enforces the use of an <code>AnnotationConfiguration</code> instance.</p>2012-01-24T00:05:32ZString LOBs on PostgreSQL with Hibernate 3.6Shredhttps://shred.zone/author-1https://shred.zone/page-2992018-07-17T20:29:37Z2011-02-24T00:35:05Z<p>For String properties that may contain more than 255 characters, it is advised to add a <code>@Lob</code> annotation to the appropriate property. For example, to keep a comment text in an entity, one would write:</p>
<pre class="prettyprint"><code class="language-java">@Lob
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
</code></pre>
<p>On PostgreSQL, a large string is usually kept in a <code>TEXT</code> column (instead of <code>VARCHAR</code>). However, after updating to Hibernate 3.6, an exception was suddenly thrown when accessing such a property (along with an <code>SQLState: 22003</code> from PostgreSQL):</p>
<pre>
org.postgresql.util.PSQLException: Bad value for type long : This is some text...
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2796)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:2019)
at org.postgresql.jdbc4.Jdbc4ResultSet.getClob(Jdbc4ResultSet.java:43)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.java:384)
... and more
</pre>
<p>Obviously, the PostgreSQL connector tried to interprete the textual content as a long integer now, which - of course - results in a failure. PostgreSQL knows two ways of storing binary large objects, either as <code>BYTEA</code> within the table space, or as <code>OID</code> in a separate place and referenced by a numerical identifier. It seems that Hibernate 3.6 suddenly treats <code>TEXT</code> columns like <code>OID</code> columns as well.</p>
<p>In the internet, I have found <a href="https://stackoverflow.com/questions/3677380/proper-hibernate-annotation-for-byte" class="exts">similar problems</a> related to <code>@Lob</code> annotated <code>byte[]</code> properties. A common solution was to add a <code>@Type</code> annotation to the property.</p>
<p>An attempt to add <code>@Type(type = "org.hibernate.type.MaterializedClobType")</code> did not help at all. Instead, <code>@Type(type = "org.hibernate.type.TextType")</code> did the trick:</p>
<pre class="prettyprint"><code class="language-java">@Lob
@Type(type = "org.hibernate.type.TextType")
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
</code></pre>
<p><strong>Update:</strong> An alternative proposed by <em>valsaraj</em> is to use <code>@Column(columnDefinition = "text")</code>, which requires not to use <code>@Lob</code> at <code>String</code>s at all:</p>
<pre class="prettyprint"><code class="language-java">@Column(columnDefinition = "text")
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
</code></pre>
<p>I think this is the better solution, however it requires the underlying database to support the <code>text</code> column type.</p>
<p>For PostgreSQL, it now works fine again, even without needing to alter the table column type. However I couldn't check the impact of the annotation on other DBMS (like Oracle). Your feedback is welcome.</p>2011-02-24T00:35:05ZHow to fetch a random entry with HibernateShredhttps://shred.zone/author-1https://shred.zone/page-532018-07-17T20:32:35Z2010-08-27T21:32:12Z<p>I recently found myself in the situation where I needed Hibernate to query a single, random entry from a table of Picture entities.</p>
<p>There is a simple way. Some DBMS allow to shuffle the result set by bringing the rows into a random order. For instance, in MySQL it is possible to use a query like this:</p>
<pre class="prettyprint"><code class="language-sql">SELECT id FROM picture ORDER BY rand() LIMIT 1;
</code></pre>
<p>Since Hibernate delegates unknown function calls to the underlying DBMS, <code>rand()</code> could be used in a HQL query as well:</p>
<pre class="prettyprint"><code class="language-java">q.createQuery("FROM picture ORDER BY rand()").setMaxResults(1);
</code></pre>
<p>However this query would require MySQL, so we would sacrifice the benefit of Hibernate acting as an abstraction layer to the underlying database. HQL on the other hand does not offer a similar function.</p>
<p>A solution is to use the pagination technique. First we count the number of entries, and then select a random entry using <code>setFirstResult()</code>. With Hibernate Criteria, it would look something like this:</p>
<pre class="prettyprint"><code class="language-java">Criterion restriction = yourRestrictions;
Object result = null; // will later contain a random entity
Criteria crit = session.createCriteria(Picture.class);
crit.add(restriction);
crit.setProjection(Projections.rowCount());
int count = ((Number) crit.uniqueResult()).intValue();
if (0 != count) {
int index = new Random().nextInt(count);
crit = session.createCriteria(Picture.class);
crit.add(restriction);
result = crit.setFirstResult(index).setMaxResults(1).uniqueResult();
}
</code></pre>
<p><code>restriction</code> contains further restrictions to the result set (like only pictures that have been published). At the end, <code>result</code> contains a random single entry from the Picture entity, or <code>null</code> if the result set was empty.</p>2010-08-27T21:32:12Z