• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Paul Clapham
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Roland Mueller
  • Piet Souris
Bartenders:

Why does EJB assume a join table and how do i get around it?

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am just starting out with EJB:s and i ran into this problem. Can someone please help me out?

I have two tables: TOURNAMENT and EVENT. They have a one-to-many relation: a tournament can have zero, one or many events.

My tables are in an Oracle XE database:

CREATE TABLE TOURNAMENT
(
ID NUMBER NOT NULL,
NAME VARCHAR2(100 BYTE),
STATUS VARCHAR2(20 BYTE),
DESCRIPTION VARCHAR2(1000 BYTE),
START_DATE DATE,
END_DATE DATE,
START_BALANCE NUMBER(10,2),
MAX_PARTICIPANTS NUMBER,
UPDTS DATE
)

CREATE TABLE EVENT
(
ID NUMBER NOT NULL,
TOURNAMENT_ID NUMBER NOT NULL,
NAME VARCHAR2(100 BYTE),
START_DATE DATE,
END_DATE DATE,
STATUS VARCHAR2(20 BYTE),
UPDTS DATE
)

Now i created a session EJB for tournament:
package oracle;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import java.sql.Timestamp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;

@Entity
@NamedQueries({
@NamedQuery(name = "Tournament.findAll", query = "select o from Tournament o"),
@NamedQuery(name = "Tournament.findByName", query = "select o from Tournament o where o.name = :P_name")
})

public class Tournament implements Serializable {
private String description;
@Column(name="END_DATE")
private Timestamp endDate;
@Id
@Column(nullable = false)
private Long id;
@Column(name="MAX_PARTICIPANTS")
private Long maxParticipants;
private String name;
@Column(name="START_BALANCE")
private Double startBalance;
@Column(name="START_DATE")
private Timestamp startDate;
private String status;
private Timestamp updts;

private List<Event> events = new ArrayList<Event>();
@OneToMany(cascade={CascadeType.ALL})
@JoinColumn(name="TOURNAMENT_ID")
public List<Event> getEvents() {
System.out.println("------------->inne i getEvents()");
return this.events;
}

public void setEvents(List<Event> inEvents) {
this.events = inEvents;
}

public Tournament() {
}

public Tournament(String description, Timestamp endDate, Long id,
Long maxParticipants, String name, Double startBalance,
Timestamp startDate, String status, Timestamp updts) {
this.description = description;
this.endDate = endDate;
this.id = id;
this.maxParticipants = maxParticipants;
this.name = name;
this.startBalance = startBalance;
this.startDate = startDate;
this.status = status;
this.updts = updts;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public Timestamp getEndDate() {
return endDate;
}

public void setEndDate(Timestamp endDate) {
this.endDate = endDate;
}

public Long getId() {
return id;
}

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

public Long getMaxParticipants() {
return maxParticipants;
}

public void setMaxParticipants(Long maxParticipants) {
this.maxParticipants = maxParticipants;
}

public String getName() {
return name;
}

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

public Double getStartBalance() {
return startBalance;
}

public void setStartBalance(Double startBalance) {
this.startBalance = startBalance;
}

public Timestamp getStartDate() {
return startDate;
}

public void setStartDate(Timestamp startDate) {
this.startDate = startDate;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public Timestamp getUpdts() {
return updts;
}

public void setUpdts(Timestamp updts) {
this.updts = updts;
}

//Workaround for serialization error
private void writeObject(ObjectOutputStream out) throws IOException {
this.events.size();
out.defaultWriteObject();
}

}

*and one for event:*

package oracle;

import java.io.Serializable;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@NamedQueries({
@NamedQuery(name = "Event.findAll", query = "select o from Event o")
})
@Table(name = "EVENT")
public class Event implements Serializable {
private Timestamp endDate;
private Long id;
private String name;
private Timestamp startDate;
private String status;
private Long tournamentId;
private Timestamp updts;

public Event() {
}

public Event(Timestamp endDate, Long id, String name, Timestamp startDate,
String status, Long tournamentId, Timestamp updts) {
this.endDate = endDate;
this.id = id;
this.name = name;
this.startDate = startDate;
this.status = status;
this.tournamentId = tournamentId;
this.updts = updts;
}

@Id
@Column(name="ID", nullable = false)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}

@Column(name="END_DATE")
public Timestamp getEndDate() {
return endDate;
}
public void setEndDate(Timestamp endDate) {
this.endDate = endDate;
}

@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

@Column(name="START_DATE")
public Timestamp getStartDate() {
return startDate;
}
public void setStartDate(Timestamp startDate) {
this.startDate = startDate;
}

@Column(name="STATUS")
public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

@Column(name="TOURNAMENT_ID", nullable = false)
public Long getTournamentId() {
return tournamentId;
}
public void setTournamentId(Long tournamentId) {
this.tournamentId = tournamentId;
}

public Timestamp getUpdts() {
return updts;
}

public void setUpdts(Timestamp updts) {
this.updts = updts;
}
}

When trying to instantiate a tournament, i get an SQL error: ORA-00942: table or view does not exist

The SQL looks like this:
SELECT t1.ID, t1.NAME, t1.STATUS, t1.UPDTS, t1.START_DATE, t1.END_DATE, t1.TOURNAMENT_ID FROM TOURNAMENT_EVENT t0, EVENT t1 WHERE ((t0.Tournament_ID = ?) AND (t1.ID = t0.events_ID))

In other words, it is assumed a join table (TOURNAMENT_EVENT) is used, when i want to join the tables by pointing the EVENT.TOURNAMENT_ID to the TOURNAMENT.ID column.

How do i get around this without using a join table?

 
author and cow tipper
Posts: 5009
1
Hibernate Spring Tomcat Server
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Take a quick look at this example of mine. Both sides of the relation are mapped. It's similar to yours. Mine is a Team has Many Players. Yours is a Tournament has many Events. Just swap the nouns to make it more appropriate to you.





They key parts are the mappings:





It creates this type of a mapping:



Which I think is closer to what you're interested in.

Here's a more detailed description of the mapping. It uses Hibernate behind the scenes, but it uses Hibernate as a JPA implementor.
Mapping One to Many Relationships between Tables with the Java Persistence API (JPA)

-Cameron McKenzie





 
Ranch Hand
Posts: 95
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi GoofBall...
(I'm sure you're soon going to get a message from someone in the admin about your name

Please... It's always nice to streamline your code in a post and avoid dumping all of your code in the post. The easier it is to read your post, the faster you'd get a response. Most people don't really have the patience to ward through very long request posts.

That said... Here goes my response to your post:

In entity relationships, there is usually an "owner" of the relationship. The owner table would have a reference column to probably the primary key column of the related entity table.
It turns out that it makes more sense to have the entity on the "many" side to maintain a column holding a reference to the entity on the "one" side. So JPA has it that the "many" side should be the owning side. Which ultimately means that you'd have to have a reference to the "one" entity declared in the "many" entity class.
Relating that to your problem... this means you'd have your code like this:

...That's the way you'd go by it. Sadly if you wanted to have it the other way... i.e. having the Tournament side be the "owning" side of the relationship, you'd have to deal with a JoinTable... and there is no @ManyToOne(mappedBy=""). So you'd most likely have the relationship bidirectional like I have it in the code. I think it works fine this way though... save yourself an extra table.

Have a great time.
Cheers.
 
Matt S Andersson
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for you help, guys. I really appreciate it. I'll test this later today and hope it solves my problem.

Yeah, i considered editing my code before posting, but i wasn't really sure what the problem was so i decide to post all availabled information right away.

And the name - well i wish my parents would have picked a less catchy one, but what can you do... "Toki" means crazy in swedish, by the way ;-)
 
Bartender
Posts: 10336
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Goofball Thunderstruck Iii, please check your private messages.
 
Matt S Andersson
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi there, i just though i'd give some feedback on this before we close it.

I tried both suggested solutions and none of them made any difference at all. I finally figured out the Tournament class is missing an "@Table" annotation. I quickly ran my test and confirmed that the error was gone and i haven't had any time to play around with this since. Hopefully i'll work on it tonight.



PS. I also changed my name as suggested.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic