-->
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.  [ 2 posts ] 
Author Message
 Post subject: Is deleting and re-inserting on many to many on SELECT serv.
PostPosted: Mon Jul 09, 2012 7:06 pm 
Newbie

Joined: Tue Jun 26, 2012 7:52 pm
Posts: 3
Hi everyone!

I'm rookie with Hibernate and I need some help with an issue.

I'm seeing Hibernate(4.1.0.Final) is deleting and then re-inserting all rows on a many-to-many relation when I'm just trying to execute a "select service"

Here I explain what I'm doing:

In my system, any object that can be saved on the data base, extends from BaseDomain. Please check I'm re-defining equals() and hashCode() methods!! (I read this can be an issue)

Code:
public abstract class BaseDomain implements IPersistentObject {

   protected String oid = OidGenerator.createId(); // oid: this just returns a UUID string.. is the ID for any object and any row in the table.
   protected Integer version;                      // version: HIBERNATE unsaved-value="null" AND optimistic-lock="version"
   private boolean removed = false;

   @Override
   public void setOid(String anOid) {
      this.oid = anOid;
   }

   @Override
   public String getOid() {
      return oid;
   }

   @Override
   public void setVersion(Integer aVersion) {
      this.version = aVersion;
   }

   @Override
   public Integer getVersion() {
      return version;
   }

   public void setRemoved(boolean removed) {
      this.removed = removed;
   }

   public boolean isRemoved() {
      return removed;
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj)
         return true;
      if (obj == null || !(this.isAPersistenObject(obj))) {
         return false;
      }

      IPersistentObject other = (IPersistentObject) obj;

      if (oid == null)
         return false;
      return oid.equals(other.getOid());
   }

   private boolean isAPersistenObject(Object obj) {
      return obj instanceof IPersistentObject;
   }

   public boolean equalsToDTO(AbstractDTO aBaseDTO) {
      return oid.equals(aBaseDTO.getOid());
   }

   @Override
   public int hashCode() {
      if (oid != null) {
         return oid.hashCode();
      } else {
         return super.hashCode();
      }
   }

   @Override
   public String toString() {
      return this.getClass().getName() + " [id=" + oid + "]";
   }
}

Then I have 2 object and a many to many relation. A Team can have many Users, here are the java classes and the hbml files:

////////////// USER /////////////////////
Code:
public class User extends BaseDomain{

   protected String userName;
   protected String password;
   
   public User() {
   }
   
   public User(String anUserName, String aPassword) {
      this.userName = anUserName;
      this.password = aPassword;
   }
   
   public String getUserName() {
      return userName;
   }

   public void setUserName(String anUserName) {
      this.userName = anUserName;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String aPassword) {
      this.password = aPassword;
   }
}

Code:
<hibernate-mapping>
   <class name="user.domain.User" table="USUARIO" optimistic-lock="version">  // I tried select-before-update="true"
      <id name="oid" column="OID">
         <generator class="assigned" />
      </id>
      <version column="version" name="version" unsaved-value="null"/>      
      <property name="userName" column="user_name" unique="true" />
      <property name="password" column="password" />
      <property name="removed" column="removed" />
   </class>

   <!-- Queries for User -->
   <query name="getUserByUserName">
        <![CDATA[from User user where user.userName = :anUserName]]>
   </query>
   <query name="getUsersByOids">
        <![CDATA[from User user where user.removed = :isRemoved and user.oid IN (:oids)]]>
   </query>
</hibernate-mapping>

////////////// TEAM /////////////////////
Code:
public class Team extends BaseDomain {

   private String name;
   private final Collection<User> users = new HashSet<User>();

   public Team() {
   }

   public Team(String aName, Collection<User> users) {
      this.name = aName;
      this.users.addAll(users);
   }

   public String getName() {
      return name;
   }

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

   public Collection<User> getUsers() {
      return users;
   }

   protected void setUsers(Collection<User> users) {
      this.users.addAll(users);
   }

   public void addUser(User anUser) {
      this.users.add(anUser);
   }
}

Code:
<hibernate-mapping>
   <class name="user.domain.team.Team" table="TEAM" optimistic-lock="version">  // I tried select-before-update="true"
      <id name="oid" column="OID">
         <generator class="assigned" />
      </id>
      
      <version column="version" name="version" unsaved-value="null"/>      
      <property name="name" column="name" unique="true" />
      
      <bag name="users" table="TEAM_USER">   // <--- THIS IS THE MANY TO MANY RELATION!
         <key column="oid_team" />
         <many-to-many column="oid_user" class="user.domain.User" />
      </bag>
   </class>

   <!-- Queries for User -->
   <query name="getTeamByName">
        <![CDATA[from Team team where team.name = :aName]]>
   </query>
</hibernate-mapping>


Then, I have the "Team service" (summarized).. And the problem...

When I try to ejecute the getTeam() method on TeamServiceImpl (see the code below), hibernate is removing and re-inserting all TEAM_USERS relation. I can add the SQL statments if is necesary.
When Hibernate does this.. the versino field on TEAM is changed.

Because I'm using Data transfer objects, I need to use a method like "checkDTOConcurrency" on any service that change any property on TEAM.

So when I try to get any TEAM and then execute any method that check the TEAM version (like remove or update), it fails throwing DTOConcurrencyException.


Code:
public class TeamServiceImpl extends AbstractServiceImpl implements TeamServiceBI {

   @Override
   public TeamDTO getTeam(String sessionToken, TeamDTO aTeamDTO) throws UnknownTeamException {
   
      // get the Team from a respository.
      Team aTeam = this.getTeamRespository().getTeamByDTO(aTeamDTO);
      // create a new Data transfer object with data from the real team.
      return (TeamDTO) TeamDTOFactory.getInstance().getDTO(aTeam);
   }
   
   @Override
   public void removeTeam(String sessionToken, TeamDTO aTeamDTOToRemove) throws DTOConcurrencyException,
         UnknownTeamException {
      ItemTracker theItemTracker = this.getItemTrackerRespository().getItemTracker();
      Team aTeam = this.getTeamRespository().getTeamByDTO(aTeamDTOToRemove);
      this.checkDTOConcurrency(aTeamDTOToRemove, aTeam);   // CHECK THIS... WHERE IS A PART OF THE PROBLEM.
      theItemTracker.removeTeam(aTeam);

   }
   
   // I add this method here so you can see it.
   final protected void checkDTOConcurrency(AbstractDTO aDTO, BaseDomain aBaseDomianObject)
         throws DTOConcurrencyException {
      if (!aDTO.getVersion().equals(aBaseDomianObject.getVersion())) {
         throw new DTOConcurrencyException("The entity that you what to modifier had been used by other user.");
      }
   }   
}

See an example of my service decoration with Spring:

//////// SOME PART OF MY APP_CONTEXT FILE ///////////
Code:
   <bean id="teamServiceTarget" class="user.service.team.TeamServiceImpl"
      parent="abstractServiceImpl">
   </bean>

   <bean id="teamService"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
      <property name="target" ref="teamServiceTarget" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="transactionAttributes">
         <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
         </props>
      </property>
      <property name="preInterceptors">
         <list>
            <bean class="base.security.ServiceSecurityPreInterceptor" /> // THIS DOES NOT MODIFIES AN OBJECT
         </list>
      </property>         
   </bean>


If is necesary to see all the code, you can check it on google code:
svn checkout http://mg-bdoo-tp-items.googlecode.com/svn/trunk/ mg-bdoo-tp-items-read-only
(You should start seeing TeamCreateServiceTest)

Thank you very much!

_________________
---
Rodrigo


Top
 Profile  
 
 Post subject: Re: Is deleting and re-inserting on many to many on SELECT serv.
PostPosted: Thu Jul 12, 2012 8:36 pm 
Newbie

Joined: Tue Jun 26, 2012 7:52 pm
Posts: 3
I still have this issue... could someone help me?

_________________
---
Rodrigo


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.