13

I'm trying to force JPA/Hibernate to generate and use only lowercase tablenames. I've implemented a NamingStrategy like this:

public class MyNamingStrategy extends DefaultNamingStrategy {

  @Override
  public String classToTableName(String className) {
    return super.classToTableName(className).toLowerCase();
  }
}

I have applied it by setting this property in persistence.xml:

<property name="hibernate.ejb.naming_strategy" value="entities.strategy.MyNamingStrategy"/>

When I do this I get this stacktrace:

SEVERE: Exception while invoking class org.glassfish.persistence.jpa.JPADeployer prepare method
org.hibernate.DuplicateMappingException: Same physical table name [planning] references several logical table names: [Planning], [OrderProductMan_Planning]
        at org.hibernate.cfg.Configuration$MappingsImpl.addTableBinding(Configuration.java:2629)
        at org.hibernate.cfg.annotations.TableBinder.buildAndFillTable(TableBinder.java:254)
        at org.hibernate.cfg.annotations.TableBinder.bind(TableBinder.java:177)

What does the

Same physical table name [planning] references several logical table names: [Planning], [OrderProductMan_Planning]

mean?

Entities from the error, simplified as much as I could. Let me know if you need the rest.

@Entity
public class Planning implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Integer id;

  private Integer qty;

  @ManyToOne
  private OrderProductMan orderProduct;

  ....
}


@Entity
@Table
public class OrderProductMan implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  private Integer opId;

  @Basic(optional = false)
  private int qty;

  @ManyToOne(optional = false)
  private ProductMan produse;

  @ManyToOne(optional = false)
  private OrderMan orders;

  @Transient
  private int totalScheduled;

  @Transient
  private int totalProduced;
   // ...
 }
nbro
  • 15,395
  • 32
  • 113
  • 196
Bogdan
  • 5,368
  • 9
  • 43
  • 62
  • Could you provide a bit more info - like the mappings of your entities. – Bozho Jan 31 '11 at 15:30
  • I've updated my question. Let me know if you need more. Thanks! – Bogdan Jan 31 '11 at 15:42
  • Are you sure you are not trying to create tables that already exist? The message: `Same physical table name [planning] references several logical table names: [Planning]` makes me think that the uppercase version might already be there and your lower cased version can't be created. Keep in mind that most DB engines are not case sensitive. – Jesse Webb May 13 '11 at 20:04

1 Answers1

2

Bogdan, thanks for posting this. I had a similar problem with case-sensitive table names for Unix/Windows portability using Hibernate/JPA/MySQL on Linux.

Like you, I set out to bind my table names as all lower-case by configuring a custom NamingStrategy in my META-INF/persistence.xml file:

<property name="hibernate.ejb.naming_strategy" value="my.package.LowerCaseNamingStrategy" />

I got the same exception: org.hibernate.DuplicateMappingException: Same physical table name... Through using the debugger, I had an epiphany that maybe I wasn't using DefaultNamingStrategy to begin with! So I changed my base class to org.hibernate.cfg.EJB3NamingStrategy. This is more appropriate when using JPA Annotations, I believe! Here was my final NamingStrategy:

package my.package;

import org.apache.commons.lang.StringUtils;
import org.hibernate.cfg.EJB3NamingStrategy;

public class LowerCaseNamingStrategy extends EJB3NamingStrategy {
    @Override
    public String classToTableName(String className) {
        return StringUtils.lowerCase(super.classToTableName(className));
    }

    @Override
    public String collectionTableName(String ownerEntity, String ownerEntityTable, String associatedEntity,
            String associatedEntityTable, String propertyName) {
        return StringUtils.lowerCase(super.collectionTableName(ownerEntity, ownerEntityTable, associatedEntity, associatedEntityTable, propertyName));
    }

    @Override
    public String logicalCollectionTableName(String tableName, String ownerEntityTable, String associatedEntityTable,
            String propertyName) {
        return StringUtils.lowerCase(super.logicalCollectionTableName(tableName, ownerEntityTable, associatedEntityTable, propertyName));
    }

    @Override
    public String tableName(String tableName) {
        return StringUtils.lowerCase(super.tableName(tableName));
    }
}

PS the previous solution by dursun did not work for me.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Steve Jones
  • 1,528
  • 19
  • 12
  • I think I solved the problem by using ImprovedNamingStrategy. This took care of everything: lowercase names+underscores; I also had an epiphany: I realized I want full control of what's happening so I ditched the JPA/annotation stuff and switched to hibernate mappings. I've been happy ever since :) – Bogdan May 16 '11 at 08:51