Showing posts with label hibernate. Show all posts
Showing posts with label hibernate. Show all posts

Thursday, September 13, 2012

Tidbit: Hibernate bashing deluxe

This short speech from JavaZone 2011 is just ingenious! It really made me laugh out lout again and again.
I can fully recommend to watch the video (it's only 9 min), you will be amused, even if you don't know much about hibernate...


Hibernate should be to programmers what cake mixes are to bakers: beneath their dignity. from JavaZone on Vimeo.

Favorite quotes:

Frameworks like Hibernate leave you with pretty much exactly the same amount of work you had to do anyway, only now you are not enjoying it at all.
I present to you: Hibernate - the naked emperor's hairy butt-cheeks!
If Hibernate was a part of your team, you wouldn't even let him anywhere near your database.
We used to write algorithms, now we are writing annotations. Are we meant to be happy about that?

Friday, September 9, 2011

Quotes of the Week: Bashing Hibernate

quotes2.jpg

Abstracting SQL often isn't a good idea from my experience.

 

Hibernate should be to programmers what cake mixes are to bakers: beneath their dignity. [...] As professional programmers, we should be more sceptical of generic frameworks like hibernate.

 

There are easier ways to do it, rather than hitting your domain model over the head with NHibernate.
- Rob Conery, Hanselminutes 249

 

Tuesday, June 15, 2010

Learned Today: Joining with Hibernate

Hibernate (and NHibernate) is able to do a lot of different kind of joins.
Unfortunately it can not do outer joins on properties that are not mapped as associations.

My goal was to get the result of the following SQL-query with an outer join:
select e.Name, d.Status, count(*) from event e
left outer join delivery d on e.Id = d.EventId
group by e.Name, d.Status

I hoped to realize the above query with Hibernate in HQL. Actually you can do joins between entities where no association is mapped:

select new ReportDto(e.Name, d.Status, count(d))
from Delivery d, StatisticalEvent e where d.EventId = e.Id
group by d.EventId, e.Name, d.Status
... unfortunately this is an inner join.

You can do outer joins with Hibernate:
select new ReportDto(e.Name, d.Status, count(d))
from Delivery d right outer join d.Event e
group by e.Name, d.Status
... unfortunately you have to have mapped the association between the two entities, since you have to feed a path to the join expression.

(Note that I do not claim this is a proper usage scenario for Hibernate. Reporting queries like this are certainly an edge case for using Hibernate.)

Thursday, April 22, 2010

.Net QuickTip: Persisting enums as strings with NHibernate

Scenario: You want to map the values of an enum-typed property of an entity as a string into the database with NHibernate.

Solution: NHibernate stores enums with their numeric value into the database as default.
In order to save the value as string, you have to use the type attribute of the property element in the xml-mapping.
As of NHibernate 2.1 you can use the type NHibernate.Type.EnumStringType<T> like this:

<property column="DataProviderConst" name="DataProvider"
   type="EnumStringType`1[[My.Namespace.DataProvider, My.Namespace]]">
(note the strange syntax to declare the generic type)

On the web there are floating a lot of articles around, telling that you have to create a derived Type of NHibernate.Type.EnumStringType for each enum, or generate a generic EnumMapper type.
This is not necessary since NH 2.1. This post finally enlightened me.

In Fluent NHibernate mapping enums to strings is the default. You don't have to do anything.
Now, if mapping enums to strings is a best practice or an antipattern is a whole different question.

Tuesday, February 3, 2009

Help needed: Mapping a bidirectional list with Hibernate

I don't understand the behavior of Hibernate when mapping a bidirectional list. The SQL statements that Hibernate produces seem not optimal to me. Can somebody enlighten me?

The scenario is the following: I have a one-to-many parent-child relationship. I map this relationship with a bidirectional list.

According to the Hibernate Annotation Reference Guide (Chapter 2.4.6.2.3. Bidirectional association with indexed collections) the mapping should look like this:
@Entity
public class Parent {

    @Id  @GeneratedValue private long id;
    @Version  private int version;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", nullable=false)
    @org.hibernate.annotations.IndexColumn(name = "parent_index")
    List<Child> children = new ArrayList<Child>();

	...

@Entity
public class Child {

    @Id @GeneratedValue private Long id;
    @Version private int version;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    private Parent parent;

	...

But in this case Hibernate produces three SQL statements when persisting a parent with one child:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)
Hibernate: update Child set parent_id=?, parent_index=? where id=?

The third statement seems to be redundant, because parent_id and parent_index seem to be set already in the second statement.

When I change the mapping and repeat the attributes 'updatable = false, insertable = false' to the declaration of the @JoinColumn in the Parent like this:
@Entity
public class Parent {

    @Id  @GeneratedValue private long id;
    @Version  private int version;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    @org.hibernate.annotations.IndexColumn(name = "parent_index")
    List<Child> children = new ArrayList<Child>();

	...

@Entity
public class Child {

    @Id @GeneratedValue private Long id;
    @Version private int version;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    private Parent parent;

	...

...then Hibernate seems to produce much more optimized SQL:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)


The client code looks like this:
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Parent newParent = new Parent();
        newParent.setName("Parent1");

        Child newChild = new Child();
        newChild.setName("Child1");

        newParent.getChildren().add(newChild);
        newChild.setParent(newParent);

        em.persist(newParent);

        em.flush();
        tx.commit();

I am using hibernate-entitymanager 3.4.0.GA.

What am I missing? Is the Hibernate Reference Guide not correct, or am I overlooking something?

Update 2009-01-06:
Ok, I was not reading the Annotations Reference Guide thoroughly enough.

In Chapter 2.2.5.3.2.1 it is stated clearly:

To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is obviously not optimized and will produce some additional UPDATE statements.

It probably would not hurt to repeat this information in Chapter 2.4.6.2.3 .

But a question remains: If I repeat the @JoinColumn attributes 'updatable = false' and 'insertable = false' on the Parent (see code above) the additional update statements seem not to get produced... is this a legitimate workaround? Or does this result in another problem?

Friday, December 26, 2008

Using JPA and Hibernate with Maven

I have been fighting a bit to set up a Maven project with JPA and Hibernate as persistence provider.

The final solution is very simple. But when you get on a wrong track at the beginning, you end up in a terrible maze...

So here the most important hint:
The JBoss repository (http://repository.jboss.org/maven2/) is quite a mess.
In the root of the repository you find directories (matching Maven GroupIds) for hibernate , hibernate-annotations and hibernate-entitymanager.
Do not use them!
They are outdated, do not provide current versions and most annoying do not declare their dependencies... so your pom will get a mess.

All dependencies should use the GroupId org.hibernate (browse into the org directory in the Maven repository).

So here is my working pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>domain</groupId>
  <artifactId>cascaded-locking</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>cascaded-locking</name>
  <url>http://maven.apache.org</url>
  <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
  </build>
    
  <dependencies>
	
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-entitymanager</artifactId>
		<version>3.4.0.GA</version>
	</dependency>
	
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.2</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

	<dependency>
		<groupId>org.apache.derby</groupId>
		<artifactId>derby</artifactId>
		<version>10.3.2.1</version>
		<scope>test</scope>
	</dependency>
	
  </dependencies>
  
  <repositories>
      <repository>
          <id>jboss</id>
          <url>http://repository.jboss.org/maven2</url>
      </repository>
  </repositories>

</project>


Related Posts Plugin for WordPress, Blogger...