hibernate.cfg.xml中如何配置物理命名策略?
Posted
技术标签:
【中文标题】hibernate.cfg.xml中如何配置物理命名策略?【英文标题】:How to configure a physical naming strategy in hibernate.cfg.xml? 【发布时间】:2018-02-18 08:05:57 【问题描述】:我正在学习 Java 和 Hibernate。现在,我很难理解如何使用自定义物理命名策略:虽然 PhysicalNamingStrategy
对象确实已实例化,但从未调用过 toPhysicalTableName
或 toPhysicalColumnName
方法——这不是我可以用调试器看到的,至少。
版本:Java 1.8、Hibernate 5.2.10.Final、macOS 10.12。
这是一个最小的项目:
@Entity
public class Cake
@Id
private long id;
private String name;
private String FLAVOUR;
private int sErViNg;
public Cake(String name, String flavour, int serving)
this.name = name;
this.FLAVOUR = flavour;
this.sErViNg = serving;
// getters and setters
public class Main
public static void main (String[] args)
Transaction tx = null;
try (
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
)
tx = session.beginTransaction();
Cake cake = new Cake("Molten Chocolate Cake", "chocolate", 1);
session.save(cake);
tx.commit();
catch (Exception e)
e.printStackTrace();
if ( tx != null )
tx.rollback();
public class AllCapsPhysicalNamingStrategy
extends PhysicalNamingStrategyStandardImpl implements Serializable
public static final AllCapsPhysicalNamingStrategy INSTANCE
= new AllCapsPhysicalNamingStrategy();
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context)
return new Identifier(name.getText().toUpperCase(), name.isQuoted());
@Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context)
return new Identifier(name.getText().toUpperCase(), name.isQuoted());
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/cake</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.physical_naming_strategy">com.example.AllCapsPhysicalNamingStrategy</property>
<mapping class="com.example.Cake"/>
</session-factory>
</hibernate-configuration>
这是我得到的表格:
[cake]> SELECT * FROM cake;
+----+-----------+-----------------------+---------+
| id | FLAVOUR | name | sErViNg |
+----+-----------+-----------------------+---------+
| 0 | chocolate | Molten Chocolate Cake | 1 |
+----+-----------+-----------------------+---------+
我希望:
+----+-----------+-----------------------+---------+
| ID | FLAVOUR | NAME | SERVING |
+----+-----------+-----------------------+---------+
| 0 | chocolate | Molten Chocolate Cake | 1 |
+----+-----------+-----------------------+---------+
我在这里做错了什么?
【问题讨论】:
您使用的是哪个版本的 Hibernate? 编辑了我手头的尽可能多的细节。以后有小版本。 看来您的原始代码/配置应该可以工作。我假设您在 hibernate.cfg.xml 文件中仔细检查了AllCapsPhysicalNamingStrategy
的完全限定路径是否正确。
@SteveChambers 我做到了。如果不是,hibernate 理所当然地抱怨AllCapsPhysicalNamingStrategy
不是PhysicalNamingStrategy
的实例。
【参考方案1】:
这没有很好的记录,但不幸的是,Hibernate 似乎不支持在 hibernate.cfg.xml 中设置的特定属性。引用a very old Hibernate forum post:
您只能在给定 Environment.java 类中设置属性 hibernate.properties 或 hibernate.cfg.xml。其余属性如 NamingStrategy 必须使用 Configuration 类进行配置。
因此建议删除该属性,而是按照 Shiv Raghuwanshi 的建议在 Configuration 实例的代码中设置它。
【讨论】:
【参考方案2】:您也可以在配置中设置。
public class Main
public static void main (String[] args)
Transaction tx = null;
try (
Configuration configuration =new Configuration();
configuration.setPhysicalNamingStrategy(new AllCapsPhysicalNamingStrategy());
SessionFactory sessionFactory = configuration.configure().buildSessionFactory();
Session session = sessionFactory.openSession();
)
tx = session.beginTransaction();
Cake cake = new Cake("Molten Chocolate Cake", "chocolate", 1);
session.save(cake);
tx.commit();
catch (Exception e)
e.printStackTrace();
if ( tx != null )
tx.rollback();
【讨论】:
啊啊!这行得通,但是用.setProperty
替换.setPhysicalNamingStrategy
不行。但我也不能在那里设置我想要的任何东西。每当我设置一个不是 PhysicalNamingProperty 的类(在 XML 中或使用 setProperty)时,我都会得到 java.lang.ClassCastException: com.example.Cake cannot be cast to org.hibernate.boot.model.naming.PhysicalNamingStrategy
。【参考方案3】:
您的配置没有问题。只是使用Configuration
对象引导休眠需要您在配置对象本身上设置 一些 配置属性。这些通过属性指定的配置将被忽略。
此外,使用配置对象引导休眠被认为是“传统”方式(as per official hibernate docs),建议使用newer way 引导休眠,如下所示。
public static void main(String[] args)
Transaction tx = null;
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure() // using "hibernate.cfg.xml"
.build();
Metadata metadata = new MetadataSources(standardRegistry).buildMetadata();
try (
SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build();
Session session = sessionFactory.openSession();)
tx = session.beginTransaction();
Cake cake = new Cake("Molten Chocolate Cake", "chocolate", 1);
session.save(cake);
tx.commit();
catch (Exception e)
e.printStackTrace();
if (tx != null)
tx.rollback();
这将选择在hibernate.cfg.xml
文件中指定为休眠属性的物理命名策略。
【讨论】:
以上是关于hibernate.cfg.xml中如何配置物理命名策略?的主要内容,如果未能解决你的问题,请参考以下文章
如何在hibernate.cfg.xml中的主配置文件中配置多个映射文件
如何使用 maven 配置 hibernate-tools 以生成 hibernate.cfg.xml、*.hbm.xml、POJO 和 DAO
hibernate.cfg.xml 中如何设置 hbm.xml 和 Annotations 的 mapping
如何使用 hibernate.properties 文件而不是 hibernate.cfg.xml