如何在hibernate.cfg.xml中配置物理命名策略?

时间:2017-09-09 16:22:33

标签: java hibernate configuration

我正在学习Java和Hibernate。现在,我无法理解如何使用自定义物理命名策略:虽然toPhysicalTableName对象确实已实例化,但toPhysicalColumnName@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 方法从未被调用 - 不是我至少可以看到调试器。

版本:Java 1.8,Hibernate 5.2.10.Final,在macOS 10.12上。

这是一个最小的项目:

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 |
+----+-----------+-----------------------+---------+

我希望:

c2 = Comment.arel_table.alias
s1 = Comment.arel_table.
  project(c2[:user_id], c2[:created_at].maximum.as('max_created_at')).
  from(c2).group('user_id').as('s1')
puts s1.to_sql
# (SELECT "comments_2"."user_id", MAX("comments_2"."created_at") AS max_created_at
#  FROM "comments" "comments_2" GROUP BY user_id) s1

我在这里做错了什么?

3 个答案:

答案 0 :(得分:3)

这个文档没有很好记录,但遗憾的是Hibernate似乎不支持在hibernate.cfg.xml中设置的特定属性。引用a very old Hibernate forum post

  

您只能在给定Environment.java类的属性中设置   hibernate.properties或hibernate.cfg.xml。其余的属性如   必须使用Configuration类配置NamingStrategy。

所以建议删除属性,而不是像Shiv Raghuwanshi所建议的那样在Configuration实例的代码中设置它。

答案 1 :(得分: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();
        }
    }
  }
}

答案 2 :(得分:1)

您的配置没有任何问题。只是使用Configuration对象引导hibernate需要您在配置对象本身上设置配置属性的某些。通过属性指定的这些配置将被忽略。

此外,使用Configuration对象引导hibernate被视为“遗留”方式(as per official hibernate docs),建议newer way引导hibernate,如下所示。

    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属性的物理命名策略。