-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: Controlling names of FK and PK generation
PostPosted: Mon Sep 27, 2004 10:56 am 
Regular
Regular

Joined: Fri Sep 03, 2004 2:01 pm
Posts: 51
Hibernate version:2.1.6


Is there a way to control (or specify) the names of the primary keys, foreign keys and indicis that Hibernate generates?

I came across the API for controlling table names, but havent yet seen one for PK/FK etc.

Nick


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 27, 2004 1:20 pm 
Regular
Regular

Joined: Fri Sep 03, 2004 2:01 pm
Posts: 51
I can control the foreign key names, but is there any way to control the PK names generated? Our DBAs "prefer" (read enforce) a system along the lines of PK_A for the primary key of table "A_RTAB".

Im digging through the Hibernate source - but in order to save myself a fruitless task, is there anyway to define the PK name?

Since the PK seems to be inherently related to the <id> mapping type, how about adding a primary-key attribute to the <id> element in order that we can set this (the DTD doesnt seem to support behaviour at the moment) ?

Is there a reason that I'm unaware of that we couldnt specify the PK name in the mapping XML?

The same goes for Index name generation, although that seems to be an artifact of Hibernate deciding to add indices to columns - maybe this is a little more complex and could be supported through the NamingStrategy interface ?

Nick


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 27, 2004 3:46 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
I don't think there is a way yet. But it should not be too difficult to hack hbm2ddl to do it the way you want.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 2:18 pm 
Regular
Regular

Joined: Fri Sep 03, 2004 2:01 pm
Posts: 51
OK, the "problem" is the CREATE TABLE generation.

Hibernate (for Oracle 8 / 9 at least) likes to do this:

CREATE TABLE
(
id integer,
PRIMARY KEY (id)
);

This causes Oracle to generate an Index called SYS_C9080980 and causes issues with our DBAs. They like the PK of table 'A' to be called A_PK.

I noticed that the Dialect class has a getAddPrimaryKeyConstraintString( String constraintName ) method, but this would require the PK to be specified outside the CREATE TABLE.

Is there a way (with the existing 2.1.6 source) to get Hibernate to stop using the PRIMARY KEY in the CREATE TABLE and instead issue a separate ALTER TABLE ADD CONSTRAINT?

Ive modified the Hibernate-Mapping DTD to allow primary-key="A_PK" in the XML, and Ive modified the Binder to read this in.

What I really need to do is swap out the PRIMARY KEY (id) line in the CREATE TABLE with something like:

CONSTRAINT a_pk PRIMARY KEY (id) (basically prepending the Oracle specific (it may not be, but I dont know about the other dialects)

If I added a new getPrimaryKeyForCreateTable() method to the dialect, leave everything as is for non-Oracle dialects, and added this, would you consider it for inclusion?

Is there a better way to do this?

Nick


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 28, 2004 3:09 pm 
Regular
Regular

Joined: Fri Sep 03, 2004 2:01 pm
Posts: 51
or, now that Ive done this, where do I submit code alterations for review?

I added a new dialect method, getCreatePrimaryKeyString(), with a default implementation of "primary key (".
The Oracle 9 dialect overrides this to:

"constraint <pkName> primary key ("

The Primary Key name is set by an additional XML attribute in the <id> element.

Binder.bindSimpleValue() checks for the existence of this value, and calls model.setPrimaryKeyName()


PersistentClass.createPrimaryKey() was modified to the following:

public void createPrimaryKey()
{
PrimaryKey pk = new PrimaryKey();
pk.setTable(table);
if( getIdentifier().getPrimaryKeyName() != null )
{
pk.setName( getIdentifier().getPrimaryKeyName() );
}
else
{
pk.setName( PK_ALIAS.toAliasString( table.getName() ) );
}

pk.addColumns( getKey().getColumnIterator() );
}


That's it. Comments?


Nick


Top
 Profile  
 
 Post subject: I like it
PostPosted: Tue Nov 15, 2005 11:04 am 
Newbie

Joined: Tue Nov 15, 2005 10:05 am
Posts: 9
Did anything further happen with this? It would be _very_ useful to us but we're not really in a position to change hibernate itself.

Cheers
mike


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 15, 2005 10:32 am 
Beginner
Beginner

Joined: Mon Aug 15, 2005 10:20 am
Posts: 32
Location: Brazil
I'm interested in this feature too. Should we file a bug on Jira?


Top
 Profile  
 
 Post subject: another way
PostPosted: Fri Dec 16, 2005 8:59 am 
Newbie

Joined: Tue Nov 15, 2005 10:05 am
Posts: 9
I did this by post-processing the DDL.
Here's most of the code, assumes the DDL is in an array of strings. compress method is an exercise for the reader.
If you use this, you owe me a beer :)
Mike


Code:
       
        Pattern createTableP = Pattern.compile("create\\s+table\\s+(\\S+)",Pattern.CASE_INSENSITIVE);
        Matcher createTableM = createTableP.matcher("");     
        Pattern pkP = Pattern.compile("primary\\s+key",Pattern.CASE_INSENSITIVE);
        Matcher pkM = pkP.matcher(""); 
        Pattern nnP = Pattern.compile("\\(?(\\S+)\\s+\\S+(\\s+not\\s+null)", Pattern.CASE_INSENSITIVE);
        Matcher nnM = nnP.matcher("");   
        Pattern ciP = Pattern.compile("create\\s+index");
        Matcher ciM = ciP.matcher("");
       
        for(int i = 0; i < createSQL.length; ++i) {
            // is it a 'create table'?
            createTableM.reset(createSQL[i]);
            if (createTableM.find()) {
                String tableName = createTableM.group(1);
               
                // if there's a 'primary key' clause, add the constraint name
                // assumes there isn't a constraint name already
                pkM.reset(createSQL[i]);
                if (pkM.find()) {                             
                    String pkc = "PK_" + compress(tableName, ORACLE_CONSTRAINT_LENGTH - 3);
                    createSQL[i] = pkM.replaceFirst("constraint " + pkc + " primary key");
                 }
               
                // for each 'not null' clause add a constraint name
                // assumes there isn't a constraint name already
                nnM.reset(createSQL[i]);
                String updatedSql = "";
                int pos = 0;
                while (nnM.find()) {
                    String nnc = "NN_" + compress(tableName + "_" + nnM.group(1), ORACLE_CONSTRAINT_LENGTH - 4);                   
                    updatedSql += createSQL[i].substring(pos, nnM.start(2)) + " constraint " + nnc;                 
                    pos = nnM.start(2);
                }
                updatedSql += createSQL[i].substring(pos);
               
                // set tablespace for 'create table'
                createSQL[i] = updatedSql + " tablespace my_data";
            }
           
            // if this is a 'create index' set the tablespace
            ciM.reset(createSQL[i]);
            if (ciM.find()) {
                createSQL[i] += " tablespace my_index";
            }
           
         }
[/code]


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.