Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » EclipseLink can't create foreign key constraints(It seems that EclipseLink has some problems creating foreign key constraints based on JPA annotations)
EclipseLink can't create foreign key constraints [message #1748542] Thu, 24 November 2016 09:00 Go to next message
Gerrit Hohl is currently offline Gerrit HohlFriend
Messages: 1
Registered: November 2016
Junior Member
Hello everyone, Smile

I'm currently trying to use EclipseLink v2.6.4 for some tests in which I need a javax.persistence.EntityManager instance. I'm using an Apache Derby in-memory database for my tests. And I want to use my JPA annotation so that EclipseLink can create the database structure when "booting up". But it seems it doesn't work correctly.

My test:

public class ArticleEntityTest {


    private EntityManagerFactory entityManagerFactory;
    private EntityManager        entityManager;


    @Before
    public void setUp() {
        Map<String, String> properties;
        org.eclipse.persistence.jpa.PersistenceProvider pp;


        properties = new HashMap<>();
        properties.put(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML,
                "META-INF/persistence-test.xml");

        pp = new org.eclipse.persistence.jpa.PersistenceProvider();
        this.entityManagerFactory = pp.createEntityManagerFactory("orderingManager", properties);
        Assert.assertNotNull("EntityManagerFactory should not be null", this.entityManagerFactory);

        this.entityManager = this.entityManagerFactory.createEntityManager();
    }


    @Test
    public void test() {
        this.entityManager.getTransaction().begin();
        this.entityManager.getTransaction().commit();
    }

	
}


META-INF/persistence-test.xml (**** are because of the forum error 'You can only use links to eclipse.org sites while you have fewer than 1 message.' Sad ):

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
	xmlns="****/xml/ns/persistence" xmlns:xsi="****/2001/XMLSchema-instance"
	xsi:schemaLocation="****/xml/ns/persistence ****/xml/ns/persistence/persistence_2_0.xsd">
	
	<persistence-unit name="orderingManager" transaction-type="RESOURCE_LOCAL">
		<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
		<class>com.sample.ejb.marketplace.ArticleEntity</class>
		<class>com.sample.ejb.marketplace.DealerEntity</class>
		<exclude-unlisted-classes>false</exclude-unlisted-classes>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
			<property name="javax.persistence.jdbc.url" value="jdbc:derby:memory:myDB;create=true" />
			<property name="eclipselink.target-database" value="Derby" />
			<property name="eclipselink.ddl-generation" value="create-tables" />
			<property name="eclipselink.logging.level.sql" value="FINE"/>
			<property name="eclipselink.logging.parameters" value="true"/>
		</properties>
	</persistence-unit>
</persistence>


The entity classes:

@MappedSuperclass
public abstract class AbstractEntity implements Serializable {


    /** The version of this class. */
    private static final long serialVersionUID = 959294142676510096L;


    /** The ID. */
    @Id
    @GeneratedValue(generator = "id")
    @GenericGenerator(name = "id", strategy = "increment")
    private Long              id;


    /**
     * <p>
     * Creates an entity.
     * </p>
     */
    public AbstractEntity() {
        super();
    }


    /**
     * <p>
     * Returns the ID.
     * </p>
     *
     * @return The ID.
     */
    public Long getId() {
        return this.id;
    }


    /**
     * <p>
     * Sets the ID.
     * </p>
     *
     * @param id
     *            The ID.
     */
    public void setId(Long id) {
        this.id = id;
    }


}


@Entity
@Table(name = "dealer", uniqueConstraints = {
        @UniqueConstraint(name = "dealer_name_unique_key", columnNames = { "name" }) })
public class DealerEntity extends AbstractEntity {


    /** The version of this class. */
    private static final long serialVersionUID = 3751322320007565926L;


    /** The name. */
    @Column(name = "name", nullable = false, length = 256)
    private String            name;


    /**
     * <p>
     * Creates a dealer.
     * </p>
     */
    public DealerEntity() {
        super();
    }


    /**
     * <p>
     * Returns the name.
     * </p>
     *
     * @return The name.
     */
    public String getName() {
        return this.name;
    }


    /**
     * <p>
     * Sets the name.
     * </p>
     *
     * @param name
     *            The name.
     */
    public void setName(String name) {
        this.name = name;
    }


}


@Entity
@Table(name = "article", uniqueConstraints = {
        @UniqueConstraint(name = "article_number_unique_key", columnNames = { "number" }) })
public class ArticleEntity extends AbstractEntity {


    /** The version of this class. */
    private static final long serialVersionUID = 7373588833516503465L;


    /** The article number. */
    @Column(name = "number", nullable = false, length = 256)
    private String            number;
    /** The name. */
    @Column(name = "name", nullable = false, length = 256)
    private String            name;
    /** The dealer. */
    @ManyToOne(targetEntity = DealerEntity.class, cascade = { CascadeType.ALL })
    @JoinColumn(name = "dealer_id", referencedColumnName = "id", nullable = false, foreignKey = @ForeignKey(name = "article_dealer_foreign_key"))
    private DealerEntity      dealer;


    /**
     * <p>
     * Creates an article.
     * </p>
     */
    public ArticleEntity() {
        super();
    }


    /**
     * <p>
     * Returns the article number.
     * </p>
     *
     * @return The article number.
     */
    public String getNumber() {
        return this.number;
    }


    /**
     * <p>
     * Sets the article number.
     * </p>
     *
     * @param number
     *            The article number.
     */
    public void setNumber(String number) {
        this.number = number;
    }


    /**
     * <p>
     * Returns the name.
     * </p>
     *
     * @return The name.
     */
    public String getName() {
        return this.name;
    }


    /**
     * <p>
     * Sets the name.
     * </p>
     *
     * @param name
     *            The name.
     */
    public void setName(String name) {
        this.name = name;
    }


    /**
     * <p>
     * Returns the dealer.
     * </p>
     *
     * @return The dealer.
     */
    public DealerEntity getDealer() {
        return this.dealer;
    }


    /**
     * <p>
     * Sets the dealer.
     * </p>
     *
     * @param dealer
     *            The dealer.
     */
    public void setDealer(DealerEntity dealer) {
        this.dealer = dealer;
    }


}


The output of the test:

[EL Fine]: 2016-11-24 09:35:04.112--Thread(Thread[main,5,main])--Configured server platform: org.eclipse.persistence.platform.server.jboss.JBossPlatform
[EL Config]: 2016-11-24 09:35:04.269--ServerSession(17037394)--Thread(Thread[main,5,main])--The access type for the persistent class [class com.sample.ejb.AbstractEntity] is set to [FIELD].
[EL Config]: 2016-11-24 09:35:04.301--ServerSession(17037394)--Thread(Thread[main,5,main])--The access type for the persistent class [class com.sample.ejb.marketplace.ArticleEntity] is set to [FIELD].
[EL Config]: 2016-11-24 09:35:04.316--ServerSession(17037394)--Thread(Thread[main,5,main])--The access type for the persistent class [class com.sample.ejb.marketplace.DealerEntity] is set to [FIELD].
[EL Config]: 2016-11-24 09:35:04.332--ServerSession(17037394)--Thread(Thread[main,5,main])--The column name for element [id] is being defaulted to: ID.
[EL Config]: 2016-11-24 09:35:04.332--ServerSession(17037394)--Thread(Thread[main,5,main])--The alias name for the entity class [class com.sample.ejb.marketplace.ArticleEntity] is being defaulted to: ArticleEntity.
[EL Config]: 2016-11-24 09:35:04.347--ServerSession(17037394)--Thread(Thread[main,5,main])--The column name for element [id] is being defaulted to: ID.
[EL Config]: 2016-11-24 09:35:04.347--ServerSession(17037394)--Thread(Thread[main,5,main])--The alias name for the entity class [class com.sample.ejb.marketplace.DealerEntity] is being defaulted to: DealerEntity.
[EL Config]: 2016-11-24 09:35:04.347--ServerSession(17037394)--Thread(Thread[main,5,main])--The column name for element [id] is being defaulted to: ID.
[EL Info]: 2016-11-24 09:35:04.41--ServerSession(17037394)--Thread(Thread[main,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.6.4.v20160829-44060b6
[EL Config]: 2016-11-24 09:35:04.425--ServerSession(17037394)--Connection(341878976)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
	platform=>DerbyPlatform
	user name=> ""
	datasource URL=> "jdbc:derby:memory:myDB;create=true"
))
[EL Config]: 2016-11-24 09:35:05.393--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--Connected: jdbc:derby:memory:myDB
	User: APP
	Database: Apache Derby  Version: 10.13.1.1 - (1765088)
	Driver: Apache Derby Embedded JDBC Driver  Version: 10.13.1.1 - (1765088)
[EL Info]: 2016-11-24 09:35:05.44--ServerSession(17037394)--Thread(Thread[main,5,main])--/file:/C:/Users/g.hohl/workspace/Test/ejb-remote-server/target/test-classes/_orderingManager login successful
[EL Fine]: 2016-11-24 09:35:05.721--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--CREATE TABLE article (ID BIGINT NOT NULL, name VARCHAR(256) NOT NULL, number VARCHAR(256) NOT NULL, dealer_id BIGINT NOT NULL, PRIMARY KEY (ID))
[EL Fine]: 2016-11-24 09:35:05.799--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--CREATE TABLE dealer (ID BIGINT NOT NULL, name VARCHAR(256) NOT NULL, PRIMARY KEY (ID))
[EL Fine]: 2016-11-24 09:35:05.799--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--ALTER TABLE article ADD CONSTRAINT article_number_un UNIQUE (number)
[EL Fine]: 2016-11-24 09:35:05.83--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--ALTER TABLE dealer ADD CONSTRAINT dealer_name_uniqu UNIQUE (name)
[EL Fine]: 2016-11-24 09:35:05.846--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--ALTER TABLE article ADD CONSTRAINT article_dealer_foreign_key FOREIGN KEY () REFERENCES  ()
[EL Fine]: 2016-11-24 09:35:05.862--ServerSession(17037394)--Thread(Thread[main,5,main])--VALUES(1)
[EL Warning]: 2016-11-24 09:35:05.862--ServerSession(17037394)--Thread(Thread[main,5,main])--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.v20160829-44060b6): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered ")" at line 1, column 76.
Error Code: 30000
Call: ALTER TABLE article ADD CONSTRAINT article_dealer_foreign_key FOREIGN KEY () REFERENCES  ()
Query: DataModifyQuery(sql="ALTER TABLE article ADD CONSTRAINT article_dealer_foreign_key FOREIGN KEY () REFERENCES  ()")
[EL Fine]: 2016-11-24 09:35:05.862--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
[EL Fine]: 2016-11-24 09:35:05.908--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--SELECT * FROM SEQUENCE WHERE SEQ_NAME = 'id'
[EL Fine]: 2016-11-24 09:35:05.971--ServerSession(17037394)--Connection(1241569743)--Thread(Thread[main,5,main])--INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('id', 0)


The funny thing: I set some breakpoints in my Eclipse IDE and stepped through the DDL creation. And one time the org.eclipse.persistence.tools.schemaframework.ForeignKeyConstraint object gets the correct source field and target field set (by calling getSourceFields().add(String) and getTargetFields().add(String) - also there are addSourceField(String) and addTargetField(String) methods). But then a 2nd time a ForeignKeyConstraint object is created for exactly the same foreign key. And that time the source field and target field are not added.

A workaround would be to use the foreignKeyDefinition attribute of the @ForeignKey annotation. But then the same information has to be added again and to be hold in sync with the rest of the annotation. That doesn't seem to be a real solution to me.

Would be great if someone could tell me where my fault is. Confused
Re: EclipseLink can't create foreign key constraints [message #1749100 is a reply to message #1748542] Thu, 01 December 2016 19:37 Go to previous message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1274
Registered: July 2009
Senior Member
You've specified the @ForeignKey annotation with only the name. Feel free to file a bug, but it looks as if you need to define the full constraint within this annotation as it overrides what EclipseLink would have generated for the joinColumn.

You could just remove the foreignKey annotation and allow EclipseLink to generate the name itself.

[Updated on: Thu, 01 December 2016 19:39]

Report message to a moderator

Previous Topic:FetchType.EAGER not always loaded eagerly
Next Topic:ValidationException Isolated Data is not currently supported within a Client
Goto Forum:
  


Current Time: Wed Nov 22 05:52:43 GMT 2017

Powered by FUDForum. Page generated in 0.01713 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software