-->
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.  [ 1 post ] 
Author Message
 Post subject: Many-to-one foreign key relationship using a String
PostPosted: Fri Dec 23, 2011 10:35 am 
Newbie

Joined: Fri Dec 23, 2011 8:23 am
Posts: 1
I am trying to implement a many-to-one foreign key relationship between two tables using Hibernate 3.3.0RC1. There are two tables, Country and Location, where the former is a reference list of country names and ISO 3166 codes and the latter contains details about sites in our application. The Location to Country relationship is that which should be many-to-one and I am attempting to use the field countryCode in Location as a foreign key to the countryCode field of Country. This field is a java.lang.String.

1. If the foreign key is based on a non-key attribute and property-ref="countryCode" it attempts to call a getCountryCode() method on a java.lang.String.
2. If the foreign key is based on a a key of the Country table, with no property-ref, it attempts to make a call to the getId() method of a Country class, but the target is clearly a java.lang.String - specifically the string representing the ISO code.
3. If I add class="com.example.odm.beans.Country" to the many-to-one it also attempts to call a Country.getId() method with the same results as 2.
Here is an anonymised version of my Country.hbm.xml:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

   <class name="com.example.odm.beans.Country" table="country">
      <id name="id">
            <column name="id" not-null="true"/>
            <generator class="native"/>
        </id>
      <property name="countryCode" not-null="true" unique="true"/>
      <property name="name"/>
   </class>

</hibernate-mapping>

The corresponding database table is:
Code:
ID                                     NOT NULL NUMBER(10)
COUNTRYCODE                    NOT NULL VARCHAR2(255 CHAR)
NAME                                VARCHAR2(255 CHAR)


The source file for the Country class is:
Code:
package com.example.odm.beans;

import java.io.Serializable;

import org.apache.commons.lang.builder.HashCodeBuilder;

import com.example.util.faces.SelectItemMappable;

import com.example.persist.IdAware;

public class Country implements Serializable, SelectItemMappable, IdAware
{
   /**
    *
    */
   private static final long serialVersionUID = 1L;
   private Integer id=-1;

   public Integer getId(){
      return this.id;
   }

   public void setId(Integer id){
      this.id=id;
   }

   public static long getSerialVersionUID()
   {
      return serialVersionUID;
   }

   public Country()
   {}

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }

   public String getCountryCode()
   {
      return countryCode;
   }

   public void setCountryCode(String iso_3166_code)
   {
      this.countryCode = iso_3166_code;
   }

   private String countryCode, name;

   public int hashCode()
   {
      return new HashCodeBuilder().append(name).hashCode();
   }

   @Override
   public String getSelectItemLabel()
   {
      return this.getName();
   }

   @Override
   public Object getSelectItemValue()
   {
      return this.getId();
   }

}


The .hbm file for Locations is:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <typedef name="LocationType" class="com.example.common.util.hibernate.GenericEnumUserType">
        <param name="enumClass">com.example.odm.beans.LocationType</param>
    </typedef>

   <class name="com.example.odm.beans.Location" table="locations" lazy="false">
      <id name="id">
         <column name="id" not-null="true"/>
         <generator class="native"/>
      </id>

      <property name="OID" not-null="true" unique="true"/>
      <property name="name" not-null="true"/>
      <property name="protocol"/>
      <property name="address"/>
      <property name="maxUsers"/>
      <property name="active"/>
      <property name="locationNumber"/>
      <property name="locationType" column="location_type" type="LocationType" not-null="true"/>
      
      <bag name="metaDataVersionRefs" table="locations_metadata_versions" lazy="true">
         <key column="location_id"/>
         <composite-element class="com.example.odm.beans.MetaDataVersionRef">
            <many-to-one name="study" class="com.example.odm.beans.Study" not-null="true"/>
            <many-to-one name="metaDataVersion" class="com.example.odm.beans.MetaDataVersion" not-null="true"/>
            <property name="effectiveDate" column="effective_date" not-null="true"/>
         </composite-element>
      </bag>
      
      <many-to-one name="countryCode" class="com.example.odm.beans.Country" column="COUNTRYCODE" not-null="true"/>

      <bag name="assignedUsers" table="users_locations" cascade="all" lazy="false">
             <key column="location_id"/>
             <composite-element class="com.example.coretailor.beans.AssignedUser">
            <many-to-one name="referent" class="com.example.odm.beans.User" cascade="all" column="user_id" not-null="true" lazy="proxy"/>
         </composite-element>
        </bag>
      
      <!-- FIXME(retnuh): need country, but needs more thought -->
      <property name="lastModifiedDate" type="timestamp"/>
      <property name="lastModifiedByIpAddress"/>
      
   </class>

   <query name="findLocations">
      select d from Location d order by d.locationNumber asc
   </query>
   
   <query name="findNextLocationNumber">
      select MAX(d.locationNumber) from Location d
   </query>

</hibernate-mapping>

The class is as follows:
Code:
package com.example.odm.beans;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.example.common.beans.Role;
import com.example.application.beans.AssignedUser;
import com.example.util.faces.SelectItemMappable;

public class Location extends AbstractODMBean implements SelectItemMappable, Comparable<Location>
{

   private static final long serialVersionUID = 3891766030120879400L;
   private static final Log log = LogFactory.getLog(User.class);

   public Location()
   {}

   public String getOID()
   {
      return oid;
   }

   public void setOID(String oid)
   {
      this.oid = oid;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }

   public LocationType getLocationType()
   {
      return locationType;
   }

   public void setLocationType(LocationType locationType)
   {
      this.locationType = locationType;
   }

   public String getProtocol()
   {
      return protocol;
   }

   public void setProtocol(String protocol)
   {
      this.protocol = protocol;
   }

   public String getAddress()
   {
      return address;
   }

   public void setAddress(String address)
   {
      this.address = address;
   }

   public Integer getMaxUsers()
   {
      return maxUsers;
   }

   public void setMaxUsers(Integer maxUsers)
   {
      this.maxUsers = maxUsers;
   }

   public Boolean isActive()
   {
      return active;
   }

   public void setActive(Boolean active)
   {
      this.active = active;
   }

   public Timestamp getLastModifiedDate()
   {
      return lastModifiedDate;
   }

   public void setLastModifiedDate(Timestamp lastModifiedDate)
   {
      this.lastModifiedDate = lastModifiedDate;
   }

   public String getLastModifiedByIpAddress()
   {
      return lastModifiedByIpAddress;
   }

   public void setLastModifiedByIpAddress(String lastModifiedByIpAddress)
   {
      this.lastModifiedByIpAddress = lastModifiedByIpAddress;
   }

   public List<MetaDataVersionRef> getMetaDataVersionRefs()
   {
      return metaDataVersionRefs;
   }

   public void setMetaDataVersionRefs(List<MetaDataVersionRef> metaDataVersionRefs)
   {
      this.metaDataVersionRefs = metaDataVersionRefs;
   }

   public void addMetaDataVersionRef(MetaDataVersionRef metaDataVersionRef)
   {
      metaDataVersionRefs.add(metaDataVersionRef);
   }

   public Integer getLocationNumber()
   {
      return this.locationNumber;
   }

   public void setLocationNumber(Integer locationNumber)
   {
      this.locationNumber = locationNumber;
   }

   public boolean equals(Object o)
   {
      if (o instanceof Location)
         return new EqualsBuilder().append(oid, ((Location)o).oid).isEquals();
      return false;
   }

   public int hashCode()
   {
      return new HashCodeBuilder().append(oid).hashCode();
   }

   public String toString()
   {
      return "[Site " + name + " oid=" + oid + "]";
   }

   @Override
   public String getSelectItemLabel()
   {
      return getName();
   }

   @Override
   public Object getSelectItemValue()
   {
      return getId();
   }



   public Boolean getActive()
   {
      return active;
   }

   public void setSubjectCount(long subjectCount)
   {
      this.subjectCount = subjectCount;
   }

   public long getSubjectCount()
   {
      return subjectCount;
   }

   public List<AssignedUser> getAssignedUsers()
   {
      return assignedUsers;
   }

   public void setAssignedUsers(List<AssignedUser> assignedUsers)
   {
      this.assignedUsers = assignedUsers;
   }

   public void addAssignedUser(User user)
   {
      assignedUsers.add(new AssignedUser(user));
   }

   public List<User> myCRAs()
   {
      List<User> cras = retrieveUsers(Role.CRA);
      return cras;
   }

   public String myCRANames()
   {
      String names = "";
      for (User user: retrieveUsers(Role.CRA)) {
         if (names.compareTo("") != 0)
            names = names + ", ";
         names = names + user.getLoginName();
      }
      return names;
   }

   public User myInvestigator()
   {
      List<User> investigators = retrieveUsers(Role.INVESTIG);
      if (investigators.size() == 1)
         return investigators.get(0);
      else if (investigators.size() == 0) {
         log.warn("No investigator assigned for Location: " + this.getName());
         return null;
      } else {
         log.warn("More then one investigators assigned for Location: " + this.getName());
         return investigators.get(0);
      }
   }

   public User myPrincipalCRC()
   {
      List<User> princCRC = retrieveUsers(Role.PRINCRC);
      if (princCRC.size() == 1)
         return princCRC.get(0);
      else if (princCRC.size() == 0) {
         log.warn("No PrincCRC assigned for Location: " + this.getName());
         return null;
      } else {
         log.warn("More then one PrincCRC assigned for Location: " + this.getName());
         return princCRC.get(0);
      }
   }

   public List<User> retrieveUsers(Role role)
   {
      List<User> users = new ArrayList<User>();
      for (AssignedUser assignedUser: assignedUsers) {
         User user = assignedUser.getReferent();
         if (role == null || user.getRole() == role)
            users.add(user);
      }
      return users;
   }

   @Override
    public int compareTo(Location o) {
        return this.locationNumber - o.getLocationNumber();
    }   
   
   public void setCountryCode(String countryCode){
      this.countryCode=countryCode;
   }
   
   public String getCountryCode(){
      return countryCode;
   }
   
   private String protocol;

   private String oid, name, address,countryCode;
   private LocationType locationType = LocationType.Site;
   private List<MetaDataVersionRef> metaDataVersionRefs = new ArrayList<MetaDataVersionRef>();
   private Integer maxUsers;
   private long subjectCount;
   private Boolean active = Boolean.TRUE;
   private Integer locationNumber;

   private Timestamp lastModifiedDate;
   private String lastModifiedByIpAddress;
   private List<AssignedUser> assignedUsers = new ArrayList<AssignedUser>();

}


The corresponding database table is:
Code:
ID                                          NOT NULL NUMBER(10)
OID                                        NOT NULL VARCHAR2(255 CHAR)
PROTOCOL                               NOT NULL VARCHAR2(255 CHAR)
ADDRESS                                 VARCHAR2(255 CHAR)
MAXUSERS                              NUMBER(10)
ACTIVE                                   NUMBER(1)
LOCATIONNUMBER                    NUMBER(10)
LOCATION_TYPE                      NOT NULL VARCHAR2(255 CHAR)
COUNTRYCODE                        NOT NULL VARCHAR2(255 CHAR)
LASTMODIFIEDDATE                 TIMESTAMP(6)
LASTMODIFIEDBYIPADDRESS      VARCHAR2(255 CHAR)

The country codes for locations are read in from an XML file, but when the call to a Hibernate save or saveOrUpdate is made the IllegalArgumentException occurs in the two cases above. How can this be solved - is it dependent on which version of Hibernate is used?


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

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.