3

I am getting the following exception and have done all this 1000 times before but now I am getting errors:

ValidationException Exception Description: [class com.smartphonedev.rsvplaw.entities.Staff] uses a non-entity [class com.smartphonedev.rsvplaw.entities.Address] as target entity in the relationship attribute [field addresses]..

here are the entities in question. Can someone help me identify what is wrong with my relationships?

<code>
@Entity
@Table(name="address")
public class Address implements Serializable,
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(name="addressType")
@Enumerated(EnumType.ORDINAL)
private AddressType addressType;

@Column(name="streetLineOne")
private String streetLineOne;

@Column(name="streetLineTwo")
private String streetLineTwo;

@Column(name="city")
private String city;

@Column(name="adState")
private String state;

@Column(name="postCode")
private String postCode;    

@OneToMany(fetch=FetchType.LAZY, targetEntity=PhoneNumber.class, cascade = {CascadeType.MERGE,   CascadeType.REFRESH, CascadeType.DETACH},orphanRemoval=true)
@JoinColumn(name="phoneNumbers")
private Collection<PhoneNumber> phoneNumbers;
…..
}

@Entity
@Table(name="staff")
public class Staff implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

//private Profile profile;
@OneToOne(fetch=FetchType.LAZY,cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
@JoinColumn(name="permission")
private Permission permission;

@OneToOne(fetch=FetchType.LAZY,cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
@JoinColumn(name="login")    
private Login login;

@Column(name="firstName")
private String firstName;

@Column(name="surnameName")
private String surnameName;

@Column(name="emailAddress")
private String emailAddress;

@OneToMany(fetch=FetchType.LAZY, targetEntity=PhoneNumber.class, cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH},orphanRemoval=true)
@JoinColumn(name="phoneNumbers")
private Collection<PhoneNumber> phoneNumbers;

@OneToMany(fetch=FetchType.LAZY, targetEntity=Address.class, cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH},orphanRemoval=true)
@JoinColumn(name="addresses")
private Collection<Address> addresses;
}
</code

Adding the phoneNumber class @Entity @Table(name="phone") public class PhoneNumber implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;

@Column(name="numberType")
@Enumerated(EnumType.ORDINAL)
private PhoneNumberType numberType;

@Column(name="phoneNumber")
private String phoneNumber;
}
</code>

Adding persistance.xml

<code>

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="RSVPLawServerPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/RSVPLaw</jta-data-source>
<class>com.smartphonedev.rsvplaw.entities.PhoneNumber</class>
<class>com.smartphonedev.rsvplaw.entities.Address</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>NONE</shared-cache-mode>
<validation-mode>CALLBACK</validation-mode>
<properties>
  <property name="eclipselink.target-server" value="SunAS9"/>  
  <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
  <property name="eclipselink.ddl-generation" value="create-tables"/>
  <property name="eclipselink.ddl-generation.output-mode" value="database"/>
  <property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
</persistence>

<code> 
Damien Cooke
  • 599
  • 10
  • 20
  • `@OneToMany` should be `mappedBy`, while `@ManyToOne` should be followed by `@JoinColumn` – guido Nov 17 '14 at 15:18
  • @guido OneToMany has "mappedBy" ONLY IF it is bidirectional ... so how do you know it is in this case when he doesnt show the PhoneNumber class? – Neil Stockton Nov 17 '14 at 18:32
  • http://stackoverflow.com/questions/11938253/jpa-joincolumn-vs-mappedby – guido Nov 17 '14 at 19:04
  • Please note they are all unidirectional – Damien Cooke Nov 17 '14 at 20:41
  • 3
    Is your class `Address` listed in the `persistence.xml` ? Looks like it's not "known" to be an entity. – geert3 Nov 18 '14 at 09:58
  • I also noticed that the Address table is not being created where the PhoneNumber one is. This is doing my head in :( – Damien Cooke Nov 18 '14 at 12:08
  • There's this comma after `implements Serializable` (suspect this is just from copy/pasting the code here). Also value `create` for `javax.persistence.schema-generation.database.action` doesn't do updates to the schema, so try `drop-and-create`. If that doesn't help try to crank up the log level and see what output you get. – geert3 Nov 18 '14 at 21:56

1 Answers1

3

I am in this same situation while separating a @ManyToMany relationship into two @OneToMany/@ManyToOne relationships, and I solved it. Here's some tips, concluded from all answers above, and my discovery:

  1. make sure the class is with annotation @Entity, and has correct Table(name=xxx).
  2. If using JPA, make sure it's in persistence.xml. If using Hibernate, make sure it's in hibernate.cfg.xml. If using both, in both files.
  3. Make sure the classes is in the same JAR as the mapping/cfg files.
  4. One thing I found: You don't have to remove mappedBy=, but you have to ensure, that the attribute name is unique in your whole project!

Like in my case: if I remove mappedBy in my @OneToMany side(while @ManyToOne side is a intermediate class for a @ManyToMany relationship, which has its own fields, so I have to make it @Entity instead of using middle table directly), EclipseLink complains for a table named "EntityA_MiddleEntity", which doesn't exist. I guess, when encountering mappedBy=xxx, EclipseLink looks for all entities with fields named xxx, and when it exists in more than one class, and one of these classes is the intermediate class for @ManyToMany, it fails to relate them. So I changed the attribute name in the middle class and all works fine.

WesternGun
  • 11,303
  • 6
  • 88
  • 157