0

Hibernate + JPA

asked 2008-07-15 15:04:19 +0800

pannekuche gravatar image pannekuche
42 1 1

Hi guys,
I need to integrate JPA+Hibernate into my ZK-webapp but it wont really work that well. When a user points to webroot, he
will be asked to login. he provides a loginname and passwort, user validation is done via db-call. this is
how it looks:

public static User validUser(String name, String pw){
        Session session = (Session) JpaUtil.getEntityManager().getDelegate();
        session.beginTransaction();
        Criteria crit = session.createCriteria(Benutzer.class)
        .add(Restrictions.and(Restrictions.eq("loginname", name),Restrictions.eq("passwort", pw)));
        User b = (User) crit.uniqueResult();
        session.getTransaction().commit();
        session.close();
}

All this works (althought it is really slow instead of just 4 users in db). the logging-mechanism says:
INFO: EntityManagerFactory for: customer is created

That looks nice ;) But every time i start a new request (e.g. usecase: the logged in user clicks on "add new customer" in the following page) with the given logged in user (in the same browser-window), a new
entitymanagerfactory is created! i get the same message that is previously provided...
INFO: EntityManagerFactory for: customer is created

it thought, with the method-call "...getEntityManager().getDelegate()" i'll just get a new
instance of a hibernatesession, and not a complete new entitymanagerfactory?!?

in my zk.xml i made the entry for resolving the persistence-unit name that the name must not be provided every time via "...getEntityManager("customer")..."

<zk>
    <preference>
        <name>JpaUtil.PersistenceUnitName</name>
        <value>customer</value>
    </preference>
	...
</zk>

how should i open a session and process a request? i already read the provided smalltalk article "Hibernate + ZK", but that dont
handles jpa-integration :(
i know, that with the code printed above, i made a session per request... i would be highly appreciated if someone gives me a code snippet or a good explanation how to handle this problem...

thanks in advance

delete flag offensive retag edit

10 Replies

Sort by ยป oldest newest

answered 2008-07-16 07:08:28 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

This looks like a typical Hibernate + ZK "ThreadLocal" issue. Let's do some experiments first. In your WEB-INF/zk.xml, specify this to disable the ZK event thread mechanism so there is no ThreadLocal issue. See if this solve your issue.

<system-config>
<disable-event-thread/>
</system-config>

And please provide your persistence.xml regarding the entitymanager so we have more information.

link publish delete flag offensive edit

answered 2008-07-16 07:50:01 +0800

pannekuche gravatar image pannekuche
42 1 1

hi!
i integrate the code above in my zk.xml but there arent any changes... for every db-call the logger says:

16.07.2008 09:46:41 org.zkoss.zkplus.jpa.JpaUtil createEntityManagerFactory:250
INFO: EntityManagerFactory for: customer is created

here is my persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence" version="1.0">
    <persistence-unit name="customer">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
            <property name="hibernate.connection.username" value="sa"/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.connection.url" value="jdbc:hsqldb:hsql://localhost/customer"/>
        </properties>
    </persistence-unit>
</persistence>

link publish delete flag offensive edit

answered 2008-07-16 13:37:40 +0800

pannekuche gravatar image pannekuche
42 1 1

EDIT:
by adding the lines you provided, some code isn't executed...

scenario: user clicks on logout, die following event, "onLogout" is fired:

window.addEventListener("onLogout", new EventListener() {

            public void onEvent(Event event) throws Exception {
                // do logout, redirect to login-page
                int state = Messagebox.show("Wollen Sie sich abmelden?", "Info", Messagebox.OK | Messagebox.CANCEL, Messagebox.EXCLAMATION);
                if (state == Messagebox.OK) {
                    Executions.sendRedirect("login.zul");
                    Sessions.getCurrent().invalidate();
                }
            }
        });

Curious, the "Messagebox.show(...)" did not appear, but the code "Executions.sendRedirect(...)" is being executed. thats very strange...

EDIT 2:
by providing another peristence provider, "toplink", the db-calls are 10 times faster compared to the hibernate-provider... however, the disadvantage is that i cannot use the criteria api provided by hibernate...
heres the persistence.xml with toplink-provider:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence">
  <persistence-unit name="customer" transaction-type="RESOURCE_LOCAL">
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="toplink.jdbc.user" value="sa"/>
      <property name="toplink.jdbc.password" value=""/>
      <property name="toplink.jdbc.url" value="jdbc:hsqldb:hsql://localhost/pipe"/>
      <property name="toplink.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
      <property name="toplink.platform.class.name" value="oracle.toplink.essentials.platform.database.HSQLPlatform"/>
    </properties>
  </persistence-unit>
</persistence>

link publish delete flag offensive edit

answered 2008-07-17 09:57:32 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

updated 2008-07-17 10:01:30 +0800

The repeat created EntityManagerFactory is a bug. Please follow
http://sourceforge.net/tracker/index.php?func=detail&aid=2020454&group_id=152762&atid=785191

/henri

link publish delete flag offensive edit

answered 2008-07-17 10:01:10 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

As for the Messagebox.show(...) issue, the behavior is "expected". The ZK event thread mechanism is the base of the "modal window" (including Messagebox). The <disable-event-thread/> disable the event thread mechanism and the Messagebox.show() will not work as it was. For a discussion, please see this smalltalk:

http://www.zkoss.org/smalltalks/hibernatezk/hibernatezk.dsp

link publish delete flag offensive edit

answered 2008-07-17 12:28:26 +0800

pannekuche gravatar image pannekuche
42 1 1

thanks for your answer. is there any workaround for solving this problem? i must use jpa (because i annoted all my classes and there is "no way back") and i would prefer the hibernate session schema because i can use the criteria-api...
do you have any idea why the hibernate-provider is 10 times slower to db-calls than the toplink-provider?

link publish delete flag offensive edit

answered 2008-07-18 06:51:41 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

updated 2008-07-18 07:20:09 +0800

The bug is fixed and shall be release in 3.0.7. Or if you are in a hurry you can write your own utility to handle the case. It is really simple.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("customer");
Executions.getCurrent().getDesktop().getWebApp.setAttribute("customer", emf);

create and cache the emf in WebApp attributes map.

EntityManager em = factory.createEntityManager()
Executions.getCurrent().setAttribute("customer-em", em);

create and cache the em in current Execution attributes.

Then within an Execution, you always get the same EntityManager.

Executions.getCurrent() will change for each HttpRequest so you don't have to worry about memory free issue.

/henri

link publish delete flag offensive edit

answered 2008-07-18 11:24:43 +0800

pannekuche gravatar image pannekuche
42 1 1

Hi Henrichen, thanks for solving this problem :)
Just one another question, how can i "load" the entitymanagerfactory on startup? now, i create the factory on the first request on server. but i want to instantiate the factory on startup. how can i do this? is there some entry needed in zk.xml?

link publish delete flag offensive edit

answered 2008-07-19 10:23:08 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

See this

http://www.zkoss.org/javadoc/3.0.0/zk/org/zkoss/zk/ui/util/WebAppInit.html

link publish delete flag offensive edit

answered 2008-07-20 17:53:18 +0800

pannekuche gravatar image pannekuche
42 1 1

Thanks for your help :)

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2008-07-15 15:04:19 +0800

Seen: 332 times

Last updated: Jul 20 '08

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More