Spring Boot + JPA:JPA似乎会自动创建表,但不确定在哪里。

huangapple go评论56阅读模式
英文:

Spring Boot + JPA : JPA seems to auto create tables but not sure where

问题

我正在练习学习一些 Spring Boot + JPA 应用程序,并且在尝试保存到数据库表时遇到问题。

似乎 JPA 正在自动生成表名,即使我已经提供了 @Table 注释。

我有一个简单的 POJO,使用 @Entity 注释标记:

@Entity
@Table(name="SongList")
public class SongList {

    @Id
    private Integer id;
    private String album;
    private String artist;
    private String title;

//Getter and Setter Methods 
}

一个扩展了 JPA CrudRepository 的接口:

import org.springframework.data.repository.CrudRepository;

public interface songRepo extends CrudRepository<SongList,Integer> {
}

一个设置数据源属性的 properties yml 文件:

spring:
  datasource:
    driverClassName : com.mysql.cj.jdbc.Driver
    url :  jdbc:mysql://localhost:3306/Songdb
    username : root
    password : learning

jpa:
    hibernate.ddl-auto : update
    generate-ddl  : false
    show-sql : true

最后是测试类:

@SpringBootTest
@RunWith(SpringRunner.class)
class DataJpaApplicationTests {

    @Autowired
    ApplicationContext context;

    @Test
    void saveSongs() {

        songRepo repo = (songRepo) context.getBean(songRepo.class);

        SongList songs = new SongList();
        songs.setId(4);
        songs.setTitle("High Hopes");
        songs.setAlbum("Panic! At the Disco");

        repo.save(songs);

    }

}

运行测试类后,我的测试失败并显示错误:

ERROR:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: java.sql.SQLSyntaxErrorException: Table 'songdb.song_list' doesn't exist

我的数据库表已经存在。数据库名为 Songdb(而不是 songdb),表名为 SongList。

我不确定表名 'song_list' 是从哪里注入的,以及为什么我的数据库名为 'songdb',而不是在 URL 中提供的 'Songdb'。

我在这里漏掉了什么?请帮助!

英文:

I am practicing/learning some Spring Boot + JPA application and keep running into issues when attempting to save to database table.

It seems JPA is auto generating table name, even though I have provided the @Table annotation.

I have a simple POJO , marked with @Entity

@Entity
@Table(name=&quot;SongList&quot;)
public class SongList {

    @Id
    private Integer id;
    private String album;
    private String artist;
    private String title;

//Getter and Setter Methods 
}

An Interface that extends JPA CrudRepository

import org.springframework.data.repository.CrudRepository;

public interface songRepo extends CrudRepository&lt;SongList,Integer&gt; {
}

A properties yml file that sets datasource properties

spring:
  datasource:
    driverClassName : com.mysql.cj.jdbc.Driver
    url :  jdbc:mysql://localhost:3306/Songdb
    username : root
    password : learning

jpa:
    hibernate.ddl-auto : update
    generate-ddl  : false
    show-sql : true

And finally Test class :

@SpringBootTest
@RunWith(SpringRunner.class)
class DataJpaApplicationTests {

	@Autowired
	ApplicationContext context;

	@Test
	void saveSongs() {

		songRepo repo = (songRepo) context.getBean(songRepo.class);

		SongList songs = new SongList();
		songs.setId(4);
		songs.setTitle(&quot;High Hopes&quot;);
		songs.setAlbum(&quot;Panic! At the Disco&quot;);

		repo.save(songs);

	}

}

Upon running the Test class , my test fails with error :

ERROR:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
Caused by: java.sql.SQLSyntaxErrorException: Table &#39;songdb.song_list&#39; doesn&#39;t exist

My database table already exists. The database is called Songdb (not songdb) and table is SongList.

I am not sure where is the table name 'song_list' being injected and why my database name is 'songdb' instead of 'Songdb' as provided in the url.

What am I missing here ? Please help!

答案1

得分: 2

因为您正在使用Spring Boot提供的默认命名策略。Hibernate使用物理策略和隐式策略映射字段名。Hibernate使用物理命名策略将逻辑名称映射到SQL表及其列。Spring Boot为这两种策略提供了默认值,spring.jpa.hibernate.naming.physical-strategy默认为org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy,以及spring.jpa.hibernate.naming.implicit-strategy默认为org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

spring-boot的默认命名策略将会:

  • 将点号替换为下划线
  • 将驼峰命名改为蛇形命名
  • 将表名转换为小写

您可以通过设置属性来更改它,例如:

spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

对于您来说,只需更改物理命名策略即可解决问题。您还可以使用org.hibernate.cfg.EJB3NamingStrategy,它会保留所提供的表名。现在您已经知道问题的原因,可以按您喜欢的方式进行修复。

如果您希望获得更多控制,还可以根据需要自定义物理命名策略。阅读:https://stackoverflow.com/questions/39162976/hibernate-naming-strategy-changing-table-names

英文:

That is because you are using the default naming strategy provided by Spring boot. Hibernate maps field names using a physical strategy and an implicit strategy. Hibernate uses the Physical Naming Strategy to map our logical names to a SQL table and its columns. Spring Boot, provides defaults for both these strategies spring.jpa.hibernate.naming.physical-strategy defaults to org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy, and
spring.jpa.hibernate.naming.implicit-strategy defaults to org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

The default naming strategy for spring-boot will :

  • Replace dots with underscores
  • Change camel case to snake case
  • Lower-case table name

You can change it by setting the property like :

spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

For you just changing the physical naming strategy will fix your issue. You could also use org.hibernate.cfg.EJB3NamingStrategy which will keep the table name as it is provided. Now that you know the cause for the issue , you can fix it ay way you like.

You could customize the physical naming strategy like you want incase you want more control. Read : https://stackoverflow.com/questions/39162976/hibernate-naming-strategy-changing-table-names

huangapple
  • 本文由 发表于 2020年9月29日 13:18:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/64113317.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定