This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 107533 - Entity Bean created from Oracle database with composite unique constraint
Summary: Entity Bean created from Oracle database with composite unique constraint
Status: RESOLVED INVALID
Alias: None
Product: javaee
Classification: Unclassified
Component: Persistence (show other bugs)
Version: 5.x
Hardware: PC Windows XP
: P3 blocker (vote)
Assignee: Andrei Badea
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-06-20 22:34 UTC by adedhia
Modified: 2008-01-15 15:59 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description adedhia 2007-06-20 22:34:07 UTC
Code Generation of Entity Beans for Database incorrectly assigns the @EmbeddedId annotation to tables with composite
unique  constraint.
Comment 1 Andrei Badea 2007-06-21 10:26:38 UTC
Does the table have a primary key? I guess it doesn't, right?
Comment 2 adedhia 2007-06-21 15:50:24 UTC
Here is the table creation script for oracle 10g/9i

  CREATE TABLE "DEV"."LOOKUP_TYPE" 
   (	"ID" NUMBER, 
	"SHORT_NAME" VARCHAR2(40 BYTE), 
	"DESCRIPTION" VARCHAR2(40 BYTE), 
	"LAST_UPDATE_ID" VARCHAR2(15 BYTE), 
	"LAST_UPDATE_TIMESTAMP" DATE, 
	"SYSTEM" NUMBER
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 32768 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "TEST" ;
 
  CREATE INDEX "DEV"."LOOKUP_TYPE_NK1" ON "DEV"."LOOKUP_TYPE" ("SHORT_NAME") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 24576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "TEST_INDEX" ;
 
  CREATE INDEX "DEV"."LOOKUP_TYPE_PK" ON "DEV"."LOOKUP_TYPE" ("ID") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 16384 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "TEST_INDEX" ;
 
  CREATE UNIQUE INDEX "DEV"."LOOKUP_TYPE_UK1" ON "DEV"."LOOKUP_TYPE" ("SHORT_NAME", "DESCRIPTION") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING COMPUTE STATISTICS 
  STORAGE(INITIAL 16384 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "TEST_INDEX" ;
 
  CREATE OR REPLACE TRIGGER "DEV"."LOOKUP_TYPE_TR1" 

BEFORE INSERT
ON lookup_type
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW

Comment 3 adedhia 2007-06-21 15:57:49 UTC
disregard the trigger info.  
Comment 4 Andrei Badea 2007-06-29 14:08:01 UTC
Thanks. I unfortunately couldn't reproduce the issue, because the Entity Classes from Database wizard detects that the
tables doesn't have a primary key and it disables it. How did you generate the entity classes? Did you invoke File - New
File - Persistence - Entity Classes from Database? If so, isn't the table disabled for you?
Comment 5 adedhia 2007-06-29 15:24:46 UTC
Yes - I used the File - New File - Persistence - Entity Classes from Database code generation option and the table
exists in the list.  I'm looking at the table schema in oracle right now and it shows that there is a primary key on ID
(I'm not sure why it didn't come across in the creation statement generated from Oracle SQL Developer. )  You may try to
add ID as the primary key and see what happens.

thanks!

Amit
Comment 6 Andrei Badea 2007-06-29 16:59:30 UTC
I did and here's what was generated in LookupType.java:

    @Id
    @Column(name = "ID", nullable = false)
    private BigDecimal id;

Can you try to generate the entity class for LOOKUP_TYPE again and see what happens?
Comment 7 adedhia 2007-06-29 17:11:27 UTC
The classes that generate are as follows:
/*
 * LookupType.java
 *
 * 
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.newenergyassoc.prototype.esc.ejb.entity;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 *
 * @author adedhia
 */
@Entity
@Table(name = "LOOKUP_TYPE")
@NamedQueries( {@NamedQuery(name = "LookupType.findById", query = "SELECT l FROM LookupType l WHERE l.id = :id"),
@NamedQuery(name = "LookupType.findByShortName", query = "SELECT l FROM LookupType l WHERE l.lookupTypePK.shortName =
:shortName"), @NamedQuery(name = "LookupType.findByDescription", query = "SELECT l FROM LookupType l WHERE
l.lookupTypePK.description = :description"), @NamedQuery(name = "LookupType.findByLastUpdateId", query = "SELECT l FROM
LookupType l WHERE l.lastUpdateId = :lastUpdateId"), @NamedQuery(name = "LookupType.findByLastUpdateTimestamp", query =
"SELECT l FROM LookupType l WHERE l.lastUpdateTimestamp = :lastUpdateTimestamp"), @NamedQuery(name =
"LookupType.findBySystem", query = "SELECT l FROM LookupType l WHERE l.system = :system")})
public class LookupType implements Serializable {
    @EmbeddedId
    protected LookupTypePK lookupTypePK;
    @Column(name = "ID", nullable = false)
    private BigInteger id;
    @Column(name = "LAST_UPDATE_ID", nullable = false)
    private String lastUpdateId;
    @Column(name = "LAST_UPDATE_TIMESTAMP", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date lastUpdateTimestamp;
    @Column(name = "SYSTEM", nullable = false)
    private BigInteger system;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "lookupTypeId")
    private Collection<Lookup> lookupCollection;

    public LookupType() {
    }

    public LookupType(LookupTypePK lookupTypePK) {
        this.lookupTypePK = lookupTypePK;
    }

    public LookupType(LookupTypePK lookupTypePK, BigInteger id, String lastUpdateId, Date lastUpdateTimestamp,
BigInteger system) {
        this.lookupTypePK = lookupTypePK;
        this.id = id;
        this.lastUpdateId = lastUpdateId;
        this.lastUpdateTimestamp = lastUpdateTimestamp;
        this.system = system;
    }

    public LookupType(String shortName, String description) {
        this.lookupTypePK = new LookupTypePK(shortName, description);
    }

    public LookupTypePK getLookupTypePK() {
        return lookupTypePK;
    }

    public void setLookupTypePK(LookupTypePK lookupTypePK) {
        this.lookupTypePK = lookupTypePK;
    }

    public BigInteger getId() {
        return id;
    }

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

    public String getLastUpdateId() {
        return lastUpdateId;
    }

    public void setLastUpdateId(String lastUpdateId) {
        this.lastUpdateId = lastUpdateId;
    }

    public Date getLastUpdateTimestamp() {
        return lastUpdateTimestamp;
    }

    public void setLastUpdateTimestamp(Date lastUpdateTimestamp) {
        this.lastUpdateTimestamp = lastUpdateTimestamp;
    }

    public BigInteger getSystem() {
        return system;
    }

    public void setSystem(BigInteger system) {
        this.system = system;
    }

    public Collection<Lookup> getLookupCollection() {
        return lookupCollection;
    }

    public void setLookupCollection(Collection<Lookup> lookupCollection) {
        this.lookupCollection = lookupCollection;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (lookupTypePK != null ? lookupTypePK.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof LookupType)) {
            return false;
        }
        LookupType other = (LookupType) object;
        if (this.lookupTypePK != other.lookupTypePK && (this.lookupTypePK == null ||
!this.lookupTypePK.equals(other.lookupTypePK))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.newenergyassoc.prototype.esc.ejb.LookupType[lookupTypePK=" + lookupTypePK + "]";
    }

}





/*
 * LookupTypePK.java
 * 
 * 
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.newenergyassoc.prototype.esc.ejb.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 *
 * @author adedhia
 */
@Embeddable
public class LookupTypePK implements Serializable {
    @Column(name = "SHORT_NAME", nullable = false)
    private String shortName;
    @Column(name = "DESCRIPTION", nullable = false)
    private String description;

    public LookupTypePK() {
    }

    public LookupTypePK(String shortName, String description) {
        this.shortName = shortName;
        this.description = description;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public String getDescription() {
        return description;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (shortName != null ? shortName.hashCode() : 0);
        hash += (description != null ? description.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof LookupTypePK)) {
            return false;
        }
        LookupTypePK other = (LookupTypePK) object;
        if (this.shortName != other.shortName && (this.shortName == null || !this.shortName.equals(other.shortName))) {
            return false;
        }
        if (this.description != other.description && (this.description == null ||
!this.description.equals(other.description))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.newenergyassoc.prototype.esc.ejb.LookupTypePK[shortName=" + shortName + ", description=" +
description + "]";
    }

}
Comment 8 Andrei Badea 2007-07-02 12:49:02 UTC
Weird. It really seems NetBeans sees there is a (SHORT_NAME, DESCRIPTION) composite primary key. Can you please send a
screenshot of the table as seen in the DB Explorer with all nodes (columns, indexes, keys) of the LOOKUP_TYPE table node
expanded?
Comment 9 Andrei Badea 2007-07-27 13:48:23 UTC
Any update on this? Note I still cannot reproduce the issue, and if I can't reproduce it I can't fix it.
Comment 10 adedhia 2007-07-30 23:58:10 UTC
Sorry - I've been on other projects and seemed to have missed this message.  I'll generate screen shots this evening
with M10.  In the meantime I have created the full DDL using sql navigator.   

-- Start of DDL Script for Table DEV.LOOKUP_TYPE
-- Generated 7/30/2007 5:55:38 PM from DEV@wldg122a

CREATE TABLE lookup_type
    (id                             NUMBER NOT NULL,
    short_name                     VARCHAR2(40) NOT NULL,
    description                    VARCHAR2(40) NOT NULL,
    last_update_id                 VARCHAR2(15) NOT NULL,
    last_update_timestamp          DATE NOT NULL,
    system                         NUMBER NOT NULL
  ,
  CONSTRAINT LOOKUP_TYPE_PK
  PRIMARY KEY (id)
  USING INDEX
  PCTFREE     10
  INITRANS    2
  MAXTRANS    255
  TABLESPACE  monaco_index
  STORAGE   (
    INITIAL     16384
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  ))
  PCTFREE     10
  INITRANS    1
  MAXTRANS    255
  TABLESPACE  monaco_data
  STORAGE   (
    INITIAL     32768
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
/




-- Indexes for LOOKUP_TYPE

CREATE INDEX lookup_type_nk1 ON lookup_type
  (
    short_name                      ASC
  )
  PCTFREE     10
  INITRANS    2
  MAXTRANS    255
  TABLESPACE  monaco_index
  STORAGE   (
    INITIAL     24576
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
/



-- Constraints for LOOKUP_TYPE

ALTER TABLE lookup_type
ADD CONSTRAINT lookup_type_uk1 UNIQUE (short_name, description)
 ON DELETE SET NULL
USING INDEX
  PCTFREE     10
  INITRANS    2
  MAXTRANS    255
  TABLESPACE  monaco_index
  STORAGE   (
    INITIAL     16384
    MINEXTENTS  1
    MAXEXTENTS  2147483645
  )
/


-- Triggers for LOOKUP_TYPE

CREATE OR REPLACE TRIGGER lookup_type_tr1
 BEFORE
  INSERT
 ON lookup_type
REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
DECLARE
    NEWID NUMBER;
Begin
   IF :NEW.SYSTEM IS NULL THEN
        :NEW.SYSTEM := 1;
   END IF;
   IF :NEW.ID IS NULL OR :NEW.ID = 0 THEN
      SELECT LOOKUP_TYPE_SEQ.NEXTVAL
      INTO NEWID
      FROM DUAL;

      :NEW.ID := NEWID;
   END IF;
End;
/

CREATE OR REPLACE TRIGGER lookup_type_tr2
 BEFORE
  INSERT OR UPDATE
 ON lookup_type
REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
Begin
    :NEW.LAST_UPDATE_ID := GET_USER;
    :NEW.LAST_UPDATE_TIMESTAMP := SYSDATE;
    :NEW.SHORT_NAME := SHORT_NAME_FIX(:NEW.SHORT_NAME);
End;
/

CREATE OR REPLACE TRIGGER lookup_type_tr3
 BEFORE
  DELETE OR UPDATE
 ON lookup_type
REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
declare
    System_Lookup_Error EXCEPTION;
begin
    IF :OLD.SYSTEM = 1 THEN
        RAISE System_Lookup_Error;
    END IF;

EXCEPTION
    WHEN System_Lookup_Error THEN
        RAISE_APPLICATION_ERROR(-20001, 'Updates and Deletions are not allowed for System Level Lookup Types.');
End;
/

CREATE OR REPLACE TRIGGER lookup_type_tr4
 AFTER
  INSERT
 ON lookup_type
REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
Begin
INSERT INTO security_role_lookup_type
    (security_role_id, lookup_type_id)
VALUES
    (0, :NEW.id);
End;
/


-- End of DDL Script for Table DEV.LOOKUP_TYPE
Comment 11 Andrei Badea 2007-10-25 15:47:13 UTC
Still no luck reproducing this :-( I tried with your script, from which I removed the triggers (because NetBeans can't
execute those statements) and modified the ALTER TABLE to 

    ALTER TABLE lookup_type
    ADD CONSTRAINT lookup_type_uk1 UNIQUE (short_name, description)

because Oracle complained about "ON DELETE SET NULL", but that shouldn't affect the entity generation. I still get 

    @Id
    @Column(name = "ID", nullable = false)
    private BigDecimal id;

Can you please post the screenshot I required in desc9? Also, at the end of the generation process a file with a
dbschema extension was created in your project. Can you please attach that file here?
Comment 12 Andrei Badea 2008-01-15 15:59:19 UTC
No reply for a long time, so closing. Please reopen with the details requested in desc12. Sorry, but I really can't fix
this issue if I can't reproduce it first.