英文:
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="SongList")
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<SongList,Integer> {
}
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("High Hopes");
songs.setAlbum("Panic! At the Disco");
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 'songdb.song_list' doesn'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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论