-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Populating data for a one-to-one relationship
PostPosted: Wed Mar 24, 2004 12:06 pm 
Senior
Senior

Joined: Wed Mar 24, 2004 11:40 am
Posts: 146
Location: Indianapolis, IN, USA
Hi,

Newbie here.

I am using Hibernate 2.0 for my project.

My object structure is as follows.


class User
{
long userId;
String username;
String password;

User createBy;
Timestamp createOn;
User updateBy;
Timestamp updateOn;
}

The corresponding database table structure is as follows (I am using SAPDB).

USER
USERID: Primary Key
USERNAME
PASSWORD
CREATEBY: Foreign Key
CREATEON
UPDATEBY: Foreign Key
UPDATEON

There is a one-to-one relationship between the User and the User object assigned to createBy and updateBy. However, I am concerned that making it a standard one-to-one relationship using the following might cause an infinite loop.

<one-to-one constrained="true" outer-join="false" class="User"/>

The following are the two issues I am trying to resolve.

1. Is there a way to specify when the one-to-one relationship is populated and when it isn't (so that the createBy/updateBy object is populated with the User but the nested createBy/updateBy objects aren't)?

2. The createBy and updateBy User objects are associated with the CREATEBY and UPDATEBY foreign keys to the USERID column in the USER table. How do I specify the foreign key to be used to get the values?


This question, or something similar may have been asked on the board previously but I couldn't find anything resembling it. Any help would be greatly appreciated.

TIA


Top
 Profile  
 
 Post subject: Follow-up
PostPosted: Wed Mar 24, 2004 3:54 pm 
Senior
Senior

Joined: Wed Mar 24, 2004 11:40 am
Posts: 146
Location: Indianapolis, IN, USA
Is this too basic for the Beginners section or is there any additional information I need to provide for this question? Since I haven't been completely flamed yet, I hope it isn't too obvious of a question. :)


Top
 Profile  
 
 Post subject: Here is what we have for something (just one admin here)
PostPosted: Wed Mar 24, 2004 4:16 pm 
Beginner
Beginner

Joined: Mon Mar 22, 2004 9:37 am
Posts: 22
Location: Willow Grove, PA
<hibernate-mapping>
<!--
look at the mapping of admin
-->

<class
name="com.diamondip.netcontrol.model.Task"
table="task"
>

<id
name="id"
type="int"
column="ID"
>
<generator class="native" />
</id>


<!-- relates to admin -->

<property
name="schedId"
type="int"
column="SCHEDID"
not-null="true"
length="11"
/>
<property
name="schedStartTime"
type="java.sql.Timestamp"
column="SCHEDSTARTTIME"
length="19"
/>
<property
name="schedType"
type="java.lang.String"
column="SCHEDTYPE"
length="8"
/>
<property
name="service"
type="java.lang.String"
column="SERVICE"
length="32"
/>
<property
name="options"
type="java.lang.String"
column="OPTIONS"
length="255"
/>
<property
name="status"
type="java.lang.String"
column="STATUS"
length="8"
/>
<property
name="scope"
type="java.lang.String"
column="SCOPE"
length="32"
/>
<property
name="scopeId"
type="int"
column="SCOPEID"
length="11"
/>
<property
name="startIpAddr"
type="java.lang.String"
column="STARTIPADDR"
length="15"
/>
<property
name="endIpAddr"
type="java.lang.String"
column="ENDIPADDR"
length="15"
/>
<property
name="sourceVendorId"
type="int"
column="SOURCEVENDORID"
length="11"
/>
<property
name="sourceModelId"
type="int"
column="SOURCEMODELID"
length="11"
/>

<property
name="sourceHwRev"
type="java.lang.String"
column="SOURCEHWREV"
length="255"
/>
<property
name="sourceImageId"
type="int"
column="SOURCEIMAGEID"
length="11"
/>
<property
name="targetImageId"
type="int"
column="TARGETIMAGEID"
length="11"
/>
<property
name="recurringType"
type="java.lang.String"
column="RECURRINGTYPE"
length="8"
/>
<property
name="recurringScope1"
type="java.lang.String"
column="RECURRINGSCOPE1"
length="16"
/>
<property
name="recurringScope2"
type="java.lang.String"
column="RECURRINGSCOPE2"
length="16"
/>
<property
name="recurringScope3"
type="java.lang.String"
column="RECURRINGSCOPE3"
length="16"
/>
<property
name="processStartTime"
type="java.sql.Timestamp"
column="PROCESSSTARTTIME"
length="19"
/>
<property
name="processendTime"
type="java.sql.Timestamp"
column="PROCESSENDTIME"
length="19"
/>
<property
name="failureRetrySpec"
type="java.lang.String"
column="FAILURERETRYSPEC"
length="255"
/>
<property
name="timeoutRetrySpec"
type="java.lang.String"
column="TIMEOUTRETRYSPEC"
length="255"
/>

<!-- associations -->
<many-to-one name="admin" class="com.diamondip.netcontrol.model.Admin" column="adminid" />

</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: performance issues
PostPosted: Wed Mar 24, 2004 4:26 pm 
Senior
Senior

Joined: Wed Mar 24, 2004 11:40 am
Posts: 146
Location: Indianapolis, IN, USA
Matt,

Thanks for the response. I guess all I need to do is create many-to-one relationships for createBy and updateBy.

Code:
<many-to-one name="createBy" class="User" column="userId" />
<many-to-one name="createBy" class="User" column="userId" />



Does this mean that the CREATEBY column in the USER table has a Foreign Key association with the USERID column in the same table?

If that is the case, I will have the first part of my issue resolved.

However, the second question regarding the potential performance issues still remains, regardless of whether you have one or more administrators. The thing is I am using the User object for audit trail on all my transactions. But that also includes the User object itself. Consequently, it seems to me like if I were to ever serialize the object, it would just keep on going in an infinite loop since every User will have a createBy and updateBy User and so on and so forth.

This has to be an issue discussed before. I just can't figure out what exactly to look for to find it.


Top
 Profile  
 
 Post subject: this works for me
PostPosted: Wed Mar 24, 2004 11:02 pm 
Beginner
Beginner

Joined: Mon Mar 22, 2004 9:37 am
Posts: 22
Location: Willow Grove, PA
With lazy loading you should not have to worry about any of infinite loop(though, i think you loop/tree would still be finite with lazy loading off)
This works for me. You can see by the example.

Code:
   public void testAdminer() throws Exception {
        AdminDAO ad = new AdminDAO();
        Iterator itr = ad.findAll().iterator();
        while (itr.hasNext()) {
            Admin a = (Admin) itr.next();
            if (a.getUpdatedBy() == null) {
                System.out.println("I am admin " + a.getFirstname() +
                        " I was updated by nobody");
            } else {
                System.out.println("I am admin " + a.getFirstname() +
                        " I was updated by " + a.getUpdatedBy().getFirstname());
            }
        }
    }


data
Quote:
'id','loginid','firstname','PASSWORD','ADMINTYPE','updatedBy'
'1','login1','god','pass','1','[NULL]'
'2','login2','child1','pass','1','1'
'3','login3','child2','pass','1','1'
'0','login4','childof2','pas','3','3'



output
Quote:
I am admin god I was updated by nobody
I am admin child1 I was updated by god
I am admin child2 I was updated by god
I am admin childof2 I was updated by child2


mapping
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
   
<hibernate-mapping>
<class
    name="com.diamondip.netcontrol.model.Admin"
    table="adminer"
>

    <id
        name="id"
        type="int"
        column="ID"
    >
        <generator class="native" />
    </id>

    <property
        name="loginid"
        type="java.lang.String"
        column="LOGINID"
        length="32"
    />
    <property
        name="password"
        type="java.lang.String"
        column="PASSWORD"
        length="255"
    />
    <property
        name="firstname"
        type="java.lang.String"
        column="FIRSTNAME"
        length="50"
    />
   
      <many-to-one name="updatedBy" column="updatedBy" class="com.diamondip.netcontrol.model.Admin"/>
   
       <property
        name="adminType"
        type="java.lang.String"
        column="ADMINTYPE"
        length="32"
        update="false"
    />

    <!-- associations -->

</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Please note, I never close my session in my DAO's
PostPosted: Wed Mar 24, 2004 11:10 pm 
Beginner
Beginner

Joined: Mon Mar 22, 2004 9:37 am
Posts: 22
Location: Willow Grove, PA
I use the session in view pattern where my session is killed (after a web request, when its thread dies, or after a timeout). My root DAO objects get session from calling currentSession from --->

Code:
package com.diamondip.netcontrol.db;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.JDBCException;
import net.sf.hibernate.MappingException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;



public class HibernateSession {
    public static final ThreadLocal session = new ThreadLocal();
    Session hibernateSession;
    private static SessionFactory sf = null;
    ApplicationContext ctx = null;
    private static Log log = LogFactory.getLog(ServiceLocator.class);   
   
    private static HibernateSession me;
   
    static {
      try
      {
         me = new HibernateSession();
      }
      catch (Exception e)
      {
         log.fatal("Error occurred initializing ServiceLocator");
         e.printStackTrace();
      }
   }
   
   
//  ~ Constructors ===========================================================

    private HibernateSession() throws HibernateException, JDBCException {
       // Try to lookup a JNDI Connection
       try {
          
          sf = HibernateSession.createConfiguration();
        
          
          if (sf == null) {
              System.out.println("session factory is null in after create config");
           }
          
          
       } catch (MappingException me) {
          if (log.isDebugEnabled()) {
             log.info("error communicating with JNDI, assuming testcase");
          }

       }
    }
   
   
    public static Session currentSession() throws ServiceException {

        Session s = (Session) session.get();
        if (s == null) {
            //SessionFactory sf;
            try {
           
                s = sf.openSession();
               
            } catch (HibernateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw new ServiceException(e);
            }
            s = (Session) createSession(s,50 * 1000); //50 sec
            session.set(s);
        }
        return s;
    }

    public static void closeSession() throws HibernateException {
        Session s = (Session) session.get();
        session.set(null);
     
        if (s != null){
       
            if (s.isOpen())
         {
            s.flush();
            s.close();

            if (log.isDebugEnabled())
            {
               log.debug("Closed hibernate session.");
            }
         }
        }
    }
   
    /**
     * The classes with mappings to add to the Configuration are enumerated here.
     * There should be a "${class}.hbm.xml" mapping file for each class
     * stored with each compiled class file.
     * <p>
     * To complete the Hibernate setup, there must be a valid "hibernate.properties"
     * file under the "classes" folder (root of the classpath),
     * which specifies the details of the database hookup.
     * <p>
     * The mapping documents and properties file is all that Hibernate requires.
     * <p>
     * @return A Configuration object
     * @throws net.sf.hibernate.MappingException if any the mapping documents can be rendered.
     */
    private static final SessionFactory createConfiguration() throws MappingException, HibernateException {
       log.info(" Hibernate plugIn configuration loaded");
      
     /* Perhaps these classes can be loaded from the config files instead of specifying them here
      */
      
      ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
   
    return ((SessionFactory) ctx.getBean("sessionFactory"));

     }
   
       
    private static Session createSession(final Session hibernate, final long timeout) {
        return (Session)Proxy.newProxyInstance(Session.class.getClassLoader(),
                    new Class[] { Session.class },
                    new InvocationHandler () {
                        Session _hibernate = hibernate;
                        TimerTask t = null;
                        Timer timer = null;
                       
                        private void renewLease() {
                            System.out.println("renew called");
                            if (timer != null) {
                                timer.cancel();
                                System.out.println("cancel timer:" + timer);
                            }
                            timer = new Timer();
                            t = new TimerTask() {
                                public void run() {
                                    try {
                                        //run session close....
                                        closeSession();
                                    } catch (HibernateException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                }
                               
                            };
                            timer.schedule(t,timeout);
                        }
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if (method.getName().equals("close")) {
                                //cancel the timer;
                                if (timer != null) {
                                    timer.cancel();
                                    return method.invoke(_hibernate,args);
                                }
                            }
                            renewLease();
                            return method.invoke(_hibernate,args);
                        }
                    });
        }
    }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.