"org.hibernate.DuplicateMappingException"错误的含义是什么?

13

我正在尝试强制JPA / Hibernate仅生成和使用小写表名。 我已经实现了这样的一种NamingStrategy:

public class MyNamingStrategy extends DefaultNamingStrategy {

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

我已经通过在persistence.xml中设置此属性来应用它:

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

当我执行此操作时,会出现以下堆栈跟踪:

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)

“Same physical table name [planning] references several logical table names: [Planning], [OrderProductMan_Planning]” 的意思是什么?

这是从错误中提取的实体,我尽量简化了它。如果你需要剩下的内容,请告诉我。

@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;
   // ...
 }

你能提供更多信息吗,比如你的实体映射? - Bozho
我已经更新了我的问题。如果您需要更多信息,请告诉我。谢谢! - Bogdan
你确定你没有试图创建已经存在的表格吗?这个信息:“同一个物理表名[planning]引用了几个逻辑表名:[Planning]”让我想到大写版本可能已经存在,而你的小写版本无法创建。请记住,大多数数据库引擎不区分大小写。 - Jesse Webb
1个回答

2

Bogdan,感谢您发布这篇文章。我在Linux上使用Hibernate/JPA/MySQL时也遇到了大小写敏感表名的类Unix/Windows可移植性问题。

和你一样,我通过在我的META-INF/persistence.xml文件中配置自定义NamingStrategy来绑定我的表名为全小写:

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

我遇到了同样的异常:org.hibernate.DuplicateMappingException: Same physical table name... 通过使用调试器,我恍然大悟,也许一开始我并没有使用DefaultNamingStrategy!所以我将我的基类更改为org.hibernate.cfg.EJB3NamingStrategy。我相信当使用JPA注释时,这更加合适!这是我的最终命名策略:

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:dursun之前的解决方案对我没有用。


我认为我通过使用ImprovedNamingStrategy解决了问题。这解决了所有问题:小写名称+下划线;我也有一个顿悟:我意识到我想要完全控制发生的事情,所以我放弃了JPA /注释内容并切换到Hibernate映射。从那以后我一直很开心 :) - Bogdan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接