Tuesday, September 19, 2017

How to configure a physical naming strategy in hibernate.cfg.xml?

Leave a Comment

I’m learning Java and Hibernate. Right now, I’m having trouble understanding how to use a custom physical naming strategy: While the PhysicalNamingStrategy object is indeed instantiated, the toPhysicalTableName or toPhysicalColumnName methods are never called – not that I can see with a debugger, at least.

Versions: Java 1.8, Hibernate 5.2.10.Final, on macOS 10.12.

Here’s a minimal project:

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

Here’s the table I get:

[cake]> SELECT * FROM cake; +----+-----------+-----------------------+---------+ | id | FLAVOUR   | name                  | sErViNg | +----+-----------+-----------------------+---------+ |  0 | chocolate | Molten Chocolate Cake |       1 | +----+-----------+-----------------------+---------+ 

I would expect:

+----+-----------+-----------------------+---------+ | ID | FLAVOUR   | NAME                  | SERVING | +----+-----------+-----------------------+---------+ |  0 | chocolate | Molten Chocolate Cake |       1 | +----+-----------+-----------------------+---------+ 

What am I doing wrong here?

3 Answers

Answers 1

This isn't very well documented but unfortunately it seems Hibernate doesn't support that particular property being set in hibernate.cfg.xml. To quote from a very old Hibernate forum post:

You can set the properties given Environment.java class only in hibernate.properties or hibernate.cfg.xml. Rest of the properties like NamingStrategy has to be configured with Configuration class.

So would recommend removing the property and instead setting this in code on the Configuration instance, as proposed by Shiv Raghuwanshi.

Answers 2

You can set in configuration also.

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();         }     }   } } 

Answers 3

There is nothing wrong with the your configuration. It is just that bootstrapping hibernate using Configuration object requires you to set some of the config property on configuration object itself. These configuration specified via properties will get ignored.

Also, bootstrapping hibernate using Configuration object is considered as "legacy" way (as per official hibernate docs) and newer way is recommended of bootstrapping the hibernate as shown below.

    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();             }         }     } 

This will pick the Physical naming strategy specified as hibernate property in hibernate.cfg.xml file.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment