openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig L Russell <Craig.Russ...@Sun.COM>
Subject Re: composite ID w/ another composite ID as a field
Date Mon, 02 Apr 2007 19:39:02 GMT
Hi Jeff,

The pattern you use for Book/Library is
> public class BookId implements Serializable {
>     private String name;
>     private String library;

The pattern you use for Page/Book is
> public class PageId implements Serializable {
>     private int number;
>     private BookId book;

Have you tried

> public class PageId implements Serializable {
>     private int number;
>     private String book;

Craig

On Apr 2, 2007, at 10:41 AM, jeff wrote:

> say i have Library, Book, and Page classes. a Library has many  
> Books, and a Book has many Pages. A Library's ID is it's name  
> (simple). A Book's ID is a composite of it's name and it's owning  
> Library's name (bidirectional relationship). A Page's ID is a  
> composite of it's number and it's owning Book's ID, a BookID.
>
> so, the PageId class starts like:
>
> public class PageId implements Serializable {
>     private int number;
>     private BookId book;
>
> the error i'm getting is at runtime ...
>
> <4|true|0.9.6-incubating>  
> org.apache.openjpa.persistence.ArgumentException: Field  
> "com.mycompany.book.Book.pages" declares  
> "com.mycompany.book.Page.book" as its mapped-by field, but this  
> field is not a direct relation.
>
> first, is what i'm trying to do even valid? i suspect it is not,  
> and the problem is that the fields of the ID class must be "simple"  
> types  (i believe the spec demands that). although, the error  
> message is a little confusing so i am not sure.
>
> it occurs to me that another way to achieve this would be to add  
> bookName and libraryName fields to the Page class, and add a  
> @PrePersist method that populates them by calling book.getName()  
> and book.getLibrary().getName(). but again this is messy because  
> that data is already in the table because of the bidirectional  
> relationship between the objects.
>
> as always, i'm open to "what are you an idiot?" responses if i am  
> just going about trying to define the Library, Book, Page  
> relationship in an obtuse manner.
>
> classes attached.
>
> The fish are biting.
> Get more visitors on your site using Yahoo! Search Marketing.
> package com.mycompany.book;
>
> import java.io.Serializable;
> import java.util.HashSet;
> import java.util.Set;
> import javax.persistence.CascadeType;
> import javax.persistence.Column;
> import javax.persistence.Entity;
> import javax.persistence.Id;
> import javax.persistence.IdClass;
> import javax.persistence.ManyToOne;
> import javax.persistence.OneToMany;
> import javax.xml.bind.annotation.XmlAttribute;
> import javax.xml.bind.annotation.XmlElement;
>
> @IdClass(com.mycompany.book.BookId.class)
> @Entity
> public class Book implements Serializable {
>     @Id
>     @Column(
>         name="BOOK_NAME",
>         nullable = false
>     )
>     @XmlAttribute (required = true)
>     private String name;
>
>     @OneToMany(
>         cascade = CascadeType.ALL,
>         mappedBy = "book"
>     )
>     @XmlElement (name = "page")
>     private Set<Page> pages = new HashSet<Page>();
>
>     @Id
>     @Column(
>         nullable = false
>     )
>     @ManyToOne (
>       cascade = CascadeType.ALL
>     )
>     private Library library;
>
>     public String getName() {
>         return name;
>     }
>
>     public void setName(String name) {
>         this.name = name;
>     }
>
>     public Page getPage(int n) {
>         for (Page p: pages) {
>             if (p.getNumber() == n) {
>                 return p;
>             }
>         }
>
>         return null;
>     }
>
>     public void putPage(Page p) {
>         p.setBook(this);
>         pages.add(p);
>     }
>
>     public boolean equals(Object o) {
>         if (!(o instanceof Book)) {
>             return false;
>         }
>
>         Book other = (Book)o;
>
>         if (!getName().equals(other.getName())) {
>             return false;
>         }
>
>         return true;
>     }
>
>     public int hashCode() {
>         return getName().hashCode();
>     }
>
>     public Library getLibrary() {
>         return library;
>     }
>
>     public void setLibrary(Library library) {
>         this.library = library;
>     }
>
> }
> package com.mycompany.book;
>
> import java.io.Serializable;
> import javax.xml.bind.annotation.XmlTransient;
>
> @XmlTransient
> public class BookId implements Serializable {
>     private String name;
>     private String library;
>
>
>     public boolean equals(Object o) {
>         if (!(o instanceof BookId)) {
>             return false;
>         }
>
>         BookId other = (BookId)o;
>
>         if (!(getName().equals(other.getName()))) {
>             return false;
>         }
>
>         if (!getLibrary().equals(other.getLibrary())) {
>             return false;
>         }
>
>         return true;
>     }
>
>     public int hashCode() {
>         return getName().hashCode() * getLibrary().hashCode();
>     }
>
>     public String getName() {
>         return name;
>     }
>
>     public void setName(String name) {
>         this.name = name;
>     }
>
>     public String getLibrary() {
>         return library;
>     }
>
>     public void setLibrary(String library) {
>         this.library = library;
>     }
> }
> package com.mycompany.book;
>
> import java.io.Serializable;
> import java.util.HashSet;
> import java.util.Set;
> import javax.persistence.CascadeType;
> import javax.persistence.Column;
> import javax.persistence.Entity;
> import javax.persistence.Id;
> import javax.persistence.OneToMany;
> import javax.xml.bind.annotation.XmlAttribute;
> import javax.xml.bind.annotation.XmlElement;
> import javax.xml.bind.annotation.XmlRootElement;
>
> @Entity
> @XmlRootElement
> public class Library implements Serializable {
>     @Id
>     @Column(
>         name="LIBRARY_NAME",
>         nullable = false
>     )
>     @XmlAttribute (name = "name", required = true)
>     private String name;
>
>     @OneToMany(
>         cascade = CascadeType.ALL,
>         mappedBy = "library"
>     )
>     @XmlElement (name = "book")
>     private Set<Book> books = new HashSet<Book>();
>
>     public String getName() {
>         return name;
>     }
>
>     public void setName(String name) {
>         this.name = name;
>     }
>
>     public Book getBook(String name) {
>         for (Book b: books) {
>             if (b.getName().equals(name)) {
>                 return b;
>             }
>         }
>
>         return null;
>     }
>
>     public void putBook(Book book) {
>         book.setLibrary(this);
>         books.add(book);
>     }
>
>     public boolean equals(Object o) {
>         if (!(o instanceof Library)) {
>             return false;
>         }
>
>         Library other = (Library)o;
>
>         if (!getName().equals(other.getName())) {
>             return false;
>         }
>
>         return true;
>     }
>
>     public int hashCode() {
>         return getName().hashCode();
>     }
>
> }
> package com.mycompany.book;
>
> import java.io.Serializable;
> import javax.persistence.CascadeType;
> import javax.persistence.Column;
> import javax.persistence.Entity;
> import javax.persistence.Id;
> import javax.persistence.IdClass;
> import javax.persistence.ManyToOne;
> import javax.xml.bind.annotation.XmlAttribute;
>
> @IdClass(com.mycompany.book.PageId.class)
> @Entity
> public class Page implements Serializable {
>     @Id
>     @Column(
>         name="PAGE_NUMBER",
>         nullable = false
>     )
>     @XmlAttribute
>     private int number;
>
>     @Id
>     @Column(
>         nullable = false
>     )
>     @ManyToOne (
>       cascade = CascadeType.ALL
>     )
>     private Book book;
>
>     public int getNumber() {
>         return number;
>     }
>
>     public void setNumber(int number) {
>         this.number = number;
>     }
>
>     public Book getBook() {
>         return book;
>     }
>
>     public void setBook(Book book) {
>         this.book = book;
>     }
> }
> package com.mycompany.book;
>
> import java.io.Serializable;
> import javax.xml.bind.annotation.XmlTransient;
>
> @XmlTransient
> public class PageId implements Serializable {
>     private int number;
>     private BookId book;
>
>     public int getNumber() {
>         return number;
>     }
>
>     public void setNumber(int number) {
>         this.number = number;
>     }
>
>     public boolean equals(Object o) {
>         if (!(o instanceof PageId)) {
>             return false;
>         }
>
>         PageId other = (PageId)o;
>
>         if (!(getNumber() == other.getNumber())) {
>             return false;
>         }
>
>         if (!getBook().equals(other.getBook())) {
>             return false;
>         }
>
>         return true;
>     }
>
>     public int hashCode() {
>         return number * getBook().hashCode();
>     }
>
>     public BookId getBook() {
>         return book;
>     }
>
>     public void setBook(BookId book) {
>         this.book = book;
>     }
> }

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message