-
1. Re: Foreign key error
waynebaylor Aug 13, 2007 5:34 PM (in response to neisan)are you saving a person before the associated address is saved?
-
2. Re: Foreign key error
neisan Aug 14, 2007 2:24 PM (in response to neisan)Hi,
I added the Column(name =?id?) annotation before the getId() method of Person and Address ejb but I?m getting the same error message about the foreign key violation. My Oracle tables have the following fields:
* Person
Name Type Nullable Default
-------- ------------- -------- -------
ID NUMBER
NAME VARCHAR2(80) Y
ADDRESSID NUMBER(10) Y
EMAIL VARCHAR2(80) Y
PASSWORD VARCHAR2(64) Y
GENDER VARCHAR2(20) Y NULL
...and some more fields
The field ID is the primary key and ADDRESSID is a foreign key.
* Address
Name Type Nullable Default
-------- ------------- -------- -------
ID NUMBER(10)
LINE1 VARCHAR2(255) Y NULL
COUNTRY VARCHAR2(150) Y NULL
POSTCODE VARCHAR2(50) Y NULL
The field ID is the primary key
I have two entity beans called Person and Address.
The data of the tables is entered using the register.jsp page that uses the Register.java class to save the contents to the tables as showed below:<f:facet name="footer"> <h:panelGroup> <h:commandButton value="#{msg.submit}" action="#{registrationBean.register}" /> <h:commandButton value="#{msg.reset}" type="reset"/> </h:panelGroup> </f:facet>
* Register.java:public String register() throws Exception { String toReturn = "failure"; if (validateData()) { try { // save locale information, in case the user chose a language on the welcome page Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); person.setLocaleCountry(locale.getCountry()); person.setLocaleLanguage(locale.getLanguage()); Context context = new InitialContext(); EntityFacade entities = (EntityFacade) context.lookup("EntityFacadeBean/remote"); person = entities.createPerson(person); toReturn = "success"; } catch (PersonEntityExistsException exist) { MessageFactory msg = new MessageFactory(); FacesContext ctx = FacesContext.getCurrentInstance(); ctx.addMessage("registerForm:email", new FacesMessage(FacesMessage.SEVERITY_ERROR, msg.getMessage("errorEmailExists"), null)); } } return toReturn; }
@Stateless public class EntityFacadeBean implements EntityFacade{ @PersistenceContext(unitName="shoestringPU") EntityManager em; public Person getPerson(String email) { Person entity = null; try { Query query = em.createQuery("SELECT p FROM Person p WHERE p.email = ?1"); query.setParameter(1, email); entity = (Person) query.getSingleResult(); } catch (NoResultException noneFound) { // if not found, just return null } return entity; } /** * Perform last minute validation, then if OK save * entities (Person and Address in Person) * @param toCreate person record to persist * @return person record just created, with the * primary key set to that just insrted. * @throws PersonEntityExistsException if email given exists * @throws PersonPasswordException if password is < 6 characters long * @throws PersonEmailException if email is blank or null */ public Person createPerson(Person toCreate) throws PersonEntityExistsException, PersonPasswordException, PersonEmailException { String email = toCreate.getEmail(); if (email == null || email.trim().length() == 0) { throw new PersonEmailException("Length is zero"); } String password = toCreate.getPassword(); if (password == null || password.length() < 6) { throw new PersonPasswordException("Length is less than 6"); } if (getPerson(email) != null) { throw new PersonEntityExistsException( "Person record already exists with an email of " + toCreate.getEmail()); } em.persist(toCreate); return toCreate; } }
The EntityFacadeBean uses a EntityManager to save the records in the table and the annotations in the beans are:
* Person.java@Entity @SequenceGenerator(name = "PERSON_SEQ", sequenceName = "PERSON_SEQ") @Id @Column(name="id") @GeneratedValue(strategy=GenerationType.AUTO, generator = "PERSON_SEQ") public int getId() { return id; } @ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="addressId", referencedColumnName="id") public Address getAddress() { return address; }
* Address.java@Id @Column(name="id") @GeneratedValue(strategy=GenerationType.AUTO, generator = "ADDRESS_SEQ") public int getId() { return id; }
The entity manager is responsible for recording the informations in the database, then shouldn?t it be recording the registers in the correct order: the Address first and the Person data after that?
Thank you.
Nei -
3. Re: Foreign key error
waynebaylor Aug 14, 2007 3:34 PM (in response to neisan)i just put together this example which mirrors your entities, and i was able to save without FK errors.
Entity Code:@Entity @SequenceGenerator(name="child_seq", sequenceName="child_seq") public class Child { private Long id; private Parent parent; private String name; public Child(){} public Child(String name) { this.name = name; } @Id @GeneratedValue(strategy=GenerationType.AUTO, generator = "child_seq") public Long getId() { return id; } public void setId(Long id) { this.id=id; } public String getName() { return name; } public void setName(String name) { this.name=name; } @ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="parentId", referencedColumnName="id") public Parent getParent() { return parent; } public void setParent(Parent parent) { this.parent=parent; } } ------------------------ @Entity @SequenceGenerator(name="parent_seq", sequenceName="parent_seq") public class Parent { private Long id; @Id @GeneratedValue(strategy=GenerationType.AUTO, generator = "parent_seq") public Long getId() { return id; } public void setId(Long id) { this.id=id; } }
The SLSB I used to create/save is:@Stateless @Local(TesterLocal.class) @LocalBinding(jndiBinding="session.Tester/local") public class Tester implements TesterLocal { @PersistenceContext(unitName="PU2") private EntityManager em; public void doWork() { for(int j=0; j<5; ++j) { Parent p = new Parent(); for(int i=0; i<5; ++i) { Child c = new Child("child-"+i); c.setParent(p); em.persist(c); } em.flush(); } } }
-
4. Re: Foreign key error
neisan Aug 15, 2007 3:57 PM (in response to neisan)Hi,
I have a JSP page that receives the data entered by the user. This page uses JSF.
* register.jsp:<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ page errorPage="errorpage.jsp" %> ... <f:facet name="footer"> <h:panelGroup> <h:commandButton value="#{msg.submit}" action="#{registrationBean.register}" /> <h:commandButton value="#{msg.reset}" type="reset"/> </h:panelGroup> </f:facet> ... <h:outputLabel for="title" value="#{msg.registrationTitle}"/> <h:panelGroup> <h:inputText id="title" value="#{registrationBean.person.title}" maxlength="45" size="10"/><f:verbatim><br/></f:verbatim> <h:outputText value=" "/><h:message for="title" styleClass="formUserError"/> </h:panelGroup> <h:outputLabel for="firstName" value="#{msg.registrationName}"/> <h:panelGroup> <h:inputText id="firstName" value="#{registrationBean.person.firstName}" maxlength="255" size="30"/><f:verbatim><br/></f:verbatim> <h:outputText value=" "/><h:message for="firstName" styleClass="formUserError"/> </h:panelGroup> ... <h:outputLabel for="line1" value="#{msg.registrationAddress1}"/> <h:panelGroup> <h:inputText id="line1" value="#{registrationBean.person.address.line1}" maxlength="255" size="50"/> <f:verbatim><br/></f:verbatim> <h:outputText value=" "/><h:message for="line1" styleClass="formUserError"/> </h:panelGroup> <h:outputLabel for="postcode" value="#{msg.registrationPostcode}"/> <h:panelGroup> <h:inputText id="postcode" value="#{registrationBean.person.address.postcode}" maxlength="50" size="20"/><f:verbatim><br/></f:verbatim> <h:outputText value=" "/><h:message for="postcode" styleClass="formUserError"/> </h:panelGroup> <h:outputLabel for="country" value="#{msg.registrationCountry}"/> <h:panelGroup> <h:inputText id="country" value="#{registrationBean.person.address.country}" maxlength="150" size="40"/><f:verbatim><br/></f:verbatim> <h:outputText value=" "/><h:message for="country" styleClass="formUserError"/> </h:panelGroup>
The JSF configuration is:
* faces-config.xml:<managed-bean> <managed-bean-name>registrationBean</managed-bean-name> <managed-bean-class>app.web.Register</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>person</property-name> <value>#{registeringPersonBean}</value> </managed-property> </managed-bean> <managed-bean> <managed-bean-name>registeringPersonBean</managed-bean-name> <managed-bean-class>app.server.entities.Person</managed-bean-class> <managed-bean-scope>none</managed-bean-scope> <managed-property> <property-name>address</property-name> <value>#{addressBean}</value> </managed-property> <managed-property> <property-name>gender</property-name> <value>Undisclosed</value> </managed-property> <managed-property> <property-name>maritalStatus</property-name> <value>Undisclosed</value> </managed-property> </managed-bean> <managed-bean> <managed-bean-name>addressBean</managed-bean-name> <managed-bean-class>app.server.entities.Address</managed-bean-class> <managed-bean-scope>none</managed-bean-scope> </managed-bean>
So when the user enters the data in the JSP/JSF page and press submit the class Register.java is called with the Person ejb data filled, is that correct? As the Person ejb has the methods getAddress and setAddress, shouldn?t the entity manager create the records in the table Address and in the table Person?
Thank you again.
Nei -
5. Re: Foreign key error
waynebaylor Aug 15, 2007 5:38 PM (in response to neisan)yes, and in the example i provided in my previous post the entity manager does exactly that.
-
6. Re: Foreign key error
neisan Sep 10, 2007 4:02 PM (in response to neisan)Hi,
Sorry the late reply but I was busy with other activities. I just discovered why my code wasn't working. I had created an Oracle before insert trigger for Person and Address table that used the sequences to insert the primary key value in the tables. I didn't realize that JBOSS invokes the sequences to generate the primary key itself.
Thank you very much for your help.
Nei