title: Set table name in Spring JPA
body: <p>I think I'm trying to do something really simple. Using Spring Boot (1.3.3.RELEASE) with JPA I want to set a table name.</p>
  
  <pre><code>@Entity
  @Table(name = "MyTable_name")
  public class MyTableData {
    ...
  }
  </code></pre>
  
  <p>What I expect in my database is a table with "MyTable_name". Seems completely reasonable to me. But that doesn't happen. I get a table with name "MY_TABLE_NAME" (H2 backend) or "my_table_name" (Postgre backend). From here on I'll stick with Postgre since my goal is to read an existing DB where I don't control the table names.</p>
  
  <p>After some research I find posts that say I should use the spring.jpa.hibernate.naming-strategy property. This doesn't help much. Setting to the most commonly recommended org.hibernate.cfg.ImprovedNamingStrategy produces the same behavior: "my_table_name". Setting to org.hibernate.cfg.EJB3NamingStrategy produces "mytable_name". Setting to org.hibernate.cfg.DefaultNamingStrategy causes application context errors in Spring's innards.</p>
  
  <p>Resigned to writing my own, I started looking at org.hibernate.cfg.ImprovedNamingStrategy. I discovered it used the deprecated org.hibernate.cfg.NamingStrategy. That suggests using NamingStrategyDelegator instead. I looked at its <a href="https://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/cfg/naming/ImprovedNamingStrategyDelegator.html" rel="noreferrer">Java docs</a> but not sure how to apply. I found <a href="https://stackoverflow.com/questions/31829368/set-hibernate-naming-strategy-as-spring-bean/31836394#31836394">this post</a>. As much as I appreciate the explanation, what is trying to be done there is more complex than what I need and I had trouble applying it.</p>
  
  <p>My question then is how can I get Spring JPA to just use the name I specify? Is there a new property for NamingStrategyDelegator use? Do I need to write my own strategy?</p>
  
  <p>=========== Update ==========================</p>
  
  <p>I think I'm converging on an answer. I created a simple Spring startup application (separate from my production project). I use H2 for the backend DB. </p>
  
  <p><a href="https://stackoverflow.com/questions/32165694/spring-hibernate-5-naming-strategy-configuration">This discussion</a> on <a href="https://stackoverflow.com/questions/32165694/spring-hibernate-5-naming-strategy-configuration">Hiberate 5 Naming</a> is very helpful. With it I figured out how to set naming strategies in Hibernate 5 like the following (in application.properties).</p>
  
  <pre><code>hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
  hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
  </code></pre>
  
  <p>I created a physical naming strategy that passed through the name (like org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl does) and prints out values. From that I see that tables names are what I want through the physical naming layer.</p>
  
  <p>I then set hibernate.show_sql=true to show generate SQL. In the generated SQL the names are also correct.</p>
  
  <p>I am examining table names using DatabaseMetaData.</p>
  
  <pre><code>private void showTables() throws SQLException {
      DatabaseMetaData dbMetadata = getConnection().getMetaData();
      ResultSet result = dbMetadata.getTables(null, null, null, new String[] { "TABLE" });
      if (result != null) {
          boolean haveTable = false;
          while (result.next()) {
              haveTable = true;
              getLogger().info("Found table {}", result.getString("TABLE_NAME"));
          }
          if (!haveTable) {
              getLogger().info("No tables found");
          }
  
      }
  }
  </code></pre>
  
  <p>I still see table names in ALL CAPS when I use the above code. This leads me to believe that DatabaseMetaData is showing all caps for some reason but the rest of the code uses the correct names. [<strong>EDIT</strong>: This conclusion is not correct. I was just confused by everything else that was happening. Later testing shows DatabaseMetaData shows table names with correct case.]</p>
  
  <p>This is not yet a complete answer because there is still some strangeness in my production code that I need to investigate. But it's close and I wanted to post an update so potential readers don't waste time.</p>
  
  <p>Here is my pass through physical naming strategy in case anyone is interested. I know it can help to see what others have done, especially when trying to find classes and packages in the Spring labyrinth.</p>
  
  <pre><code>package my.domain.eric;
  
  import java.io.Serializable;
  
  import org.hibernate.boot.model.naming.Identifier;
  import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
  import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  public class NamingStrategyPhysicalLeaveAlone implements PhysicalNamingStrategy, Serializable {
      private static final long serialVersionUID = -5937286882099274612L;
  
      private static final Logger LOGGER = LoggerFactory.getLogger(NamingStrategyPhysicalLeaveAlone.class);
  
      protected Logger getLogger() {
          return LOGGER;
      }
  
      @Override
      public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment context) {
          String nameText = name == null ? "" : name.getText();
          getLogger().info("toPhysicalCatalogName name: {}", nameText);
          return name;
      }
  
      @Override
      public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment context) {
          String nameText = name == null ? "" : name.getText();
          getLogger().info("toPhysicalSchemaName name: {}", nameText);
          return name;
      }
  
      @Override
      public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
          String nameText = name == null ? "" : name.getText();
          getLogger().info("toPhysicalTableName name: {}", nameText);
          return name;
      }
  
      @Override
      public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment context) {
          String nameText = name == null ? "" : name.getText();
          getLogger().info("toPhysicalSequenceName name: {}", nameText);
          return name;
      }
  
      @Override
      public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
          String nameText = name == null ? "" : name.getText();
          getLogger().info("toPhysicalColumnName name: {}", nameText);
          return name;
      }
  }
  </code></pre>