-->
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.  [ 10 posts ] 
Author Message
 Post subject: Embedded object and inheritance problem
PostPosted: Wed Mar 29, 2006 7:33 pm 
Newbie

Joined: Thu Aug 12, 2004 10:27 am
Posts: 17
Hibernate version: 3.1.3

Hibernate annotations version: 3.1beta8

Name and version of the database you are using: mysql 4.1.12a

Dialect: org.hibernate.dialect.MySQLInnoDBDialect

Hi,
I am having a problem when embedding an object using the @Embedded annotation. The problem is that Hibernate does not correctly map the embedded class attributes. I think this could be related to the fact that the embedded object is a subclass and the mapped attribute is present in the superclass. Here is my code:

Code:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Conteudo implements Serializable {
   private Long id;
        // more code
   private ConteudoImagem imagem;
        // more code

   @Id @GeneratedValue
   public Long getId() {
      return id;
   }

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

   @Embedded
   public ConteudoImagem getImagem(){
      return imagem;
   }

   public void setImagem(ConteudoImagem img) {
      imagem = img;
   }


My embeddable class:

Code:
@Embeddable
public class ConteudoImagem extends Imagem{

        // more code

   @Transient
   public String getGrande(){
      return getImagemPath(GRANDE);
   }
   
   @Transient
   public String getMedia(){
      return getImagemPath(MEDIA);
   }

   @Transient
   public String getPequena(){
      return getImagemPath(PEQUENA);
   }
        // more code
}


The superclass of my embeddable class:

Code:
@Embeddable
public abstract class Imagem implements Serializable {
   private String imagem;
        // more code

   public String getImagem(){
      return imagem;
   }
   
   public void setImagem(String img){
      imagem=img;
   }
        // more code
}


My conteudo table should be mapped like this:
Code:
create table Conteudo (id bigint not null auto_increment, ... , imagem varchar(255) ... ) type=InnoDB;


but, for some reason, the "imagem" attribute inherited by ConteudoImagem is not mapped at all.

However, if I override the Imagem.getImagem() method in ConteudoImagem like this:

Code:
@Embeddable
public class ConteudoImagem extends Imagem{

        // more code

   @Override
   public String getImagem(){
      return super.getImagem();
   }

   @Transient
   public String getGrande(){
      return getImagemPath(GRANDE);
   }
   
   @Transient
   public String getMedia(){
      return getImagemPath(MEDIA);
   }

   @Transient
   public String getPequena(){
      return getImagemPath(PEQUENA);
   }

        // more code
}


Then the "imagem" attribute is correctly mapped. Please, notice that in the second version of ConteudoImagem I override the Imagem.getImagem() method. That's why I think the problem might be related to inheritance.

Another funny thing is that everything works fine if I remove the @Embedded annotation from the Conteudo.getImagem() method.

Can anyone help me?

Thanks,
Jair[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 29, 2006 10:16 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
I don't know about the annotations, but your analysis of the reason that hibernate is not mapping superclasses' properties in this situation is correct. Conteundo will have to associate to Imagem, not any of Imagem's subclasses. You can restrict the Imagems that go into the association: if you weren't using annotations, you'd use the where="" attribute.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 30, 2006 10:40 am 
Newbie

Joined: Thu Aug 12, 2004 10:27 am
Posts: 17
Is there any problem if I keep using a subclass of Imagem as am embedded object and override the getImagem() method the way I did? Will hibernate behave correctly in this situation?
Is there any plans to add subclass support for embedded objects? Is it something hard to implement? I think it would be a nice feature :-)
Thank you very much for your help.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 30, 2006 5:35 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Everything you need is already implemented. If all the Imagems in the set are ConteudoImagem, then that will work exactly the way you expect it to; if you put a where="???" attribute in the set mapping (I don't know how to do that with annotations, but it must be possible) then hibernate won't put any non-ConteudoImagems into the set when loading it; and it's up to business logic to prevent you from adding new Imagems that aren't ConteudoImagems.

Further, if you want to add typechecking safety to your set, what you can do is map the set with a private name ("InternalConteudoImagems", or whatever), then add these methods to the class that contains the set of Imagems:
Code:
@SupressWarnings("unchecked")
public Set<ConteudoImagem> getConteudoImagems()
{
  return (Set<ConteudoImagem>) getInternalImagems();
}

Set<Imagem> getInternalImagems()
{
  return m_colImagems;
}

void setInternalImagems(Set<Imagem> imagems)
{
  m_colImagems = imagems;
}
hibernate will use the 2nd and 3rd methods, the 1st method willl be for use in normal java code.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 03, 2006 4:33 pm 
Newbie

Joined: Thu Aug 12, 2004 10:27 am
Posts: 17
Thank you very much for your help.
I'll try that!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 03, 2006 5:15 pm 
Newbie

Joined: Thu Aug 12, 2004 10:27 am
Posts: 17
I was trying the solution you suggested but then I noticed that the "where" attribute is only usable in a collection mapping. Please notice that in my example I have a single ConteudoImagem attribute in Conteudo class. I don't have a Set of ConteudoImagem nor a Set of Imagem.
Do you have any other suggestions to help me map a single ConteudoImagem attribute in Conteudo class so that the ConteudoImagem.imagem inherited attribute is correctly mapped?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 03, 2006 5:56 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
If it's a single association, then is there any actual risk of the wrong type of Imagem being used? After all, the id of the one and only imagem in the association is right there in the table.

So long as your java code never puts the wrong type of object in the association, there shouldn't be any problem. Don't bother trying to restrict it in hibernate: in the mapping, treat the object as a plain old Imagem the whole time, and in java, you can provide a "getConteundoImagem()" method that returns "(ConteundoImagem) getImagem();".


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 03, 2006 6:55 pm 
Newbie

Joined: Thu Aug 12, 2004 10:27 am
Posts: 17
Quote:
If it's a single association, then is there any actual risk of the wrong type of Imagem being used? After all, the id of the one and only imagem in the association is right there in the table.

There's no risk of the wrong type of Imagem being used because the getters and setters for the imagem attribute only allow objects of type ConteudoImagem. By the way, Imagem and ConteudoImagem don't have an id because they are embeddable objects. Should they have an id even if they are embeddable objects and the Conteudo.imagem attribute is mapped as embedded?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 03, 2006 7:09 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
I'm afraid you're asking the wrong person. I don't know what "embedded" means in this context. I'm guessing that it has something to do with components, lobs or both, but beyond that.. no idea.

The problem with using ConteundoImagem return types for an object that is allowed to be (but won't ever actually be) an Imagem, is that hibernate may get classcast exceptions. You may have to change that.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 04, 2006 11:50 am 
Newbie

Joined: Thu Aug 12, 2004 10:27 am
Posts: 17
Embedded means in this context that ImagemConteudo is a component.
Thank you very much for your help.


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