SpringBoot 集成Spring Data JPA时,解决@Column注解name属性不生效,并兼容原来存在表的方案

作者简介:
🌹 作者:暗夜91
🤟 个人主页:暗夜91的主页
📝 微信公众号: 程序员的知识站 ,关注本人公众号,学习更多前沿知识。


具体问题:

最近项目遇到了一个因为Spring Data JPA命名策略的原因导致的数据库表与实体类映射错误的问题,具体问题如下:

数据库中已经有一批业务表了,字段命名方式是用 “_” 连接,然后其他组的人员创建数据表的时候,使用的是驼峰方式直接在数据库中创建的表,没有使用统一的命名方式。数据表中已经跑入了大量的数据,如果修改表结构的话,需要联系其他组人员修改代码,重新跑入数据,成本太高,不现实,只能在java端通过其他技术解决。

在java代码中,创建该表对应的实体类时,在对应的驼峰字段上使用@Column注解进行标注,结果发现启动项目的时候,@Column的注解没有生效,在表中创建了大量使用 “_” 连接的冗余字段。

原因分析:

数据库中的业务表是使用JPA自动在数据库中创建,所以表中 “_” 连接的字段是JPA生成的,查询发现JPA默认的命名策略是默认的隐式策略,会把所有的字段名称转为小写,并且在大写字母前面加上横线,比如testId映射到数据库中是test_id。

解决方法:

元凶找到了,接下来就是解决方法了。

Spring Data JPA是在 Hibernate 的基础之上的封装实现,所以我们可以使用Hibernate的命名规则,在properties文件中加入一下配置:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

重新启动服务,然后对数据表与实体类的映射比对,发现这次映射成功,可以在代码中使用jpa操作数据表了。

解决了数据表的映射以后,本以为万事大吉,结果查看启动日志时发现了问题,日志中显示在原本存在的业务表中添加了好多驼峰形式的字段,瞬间就麻瓜了,发现这种处理方式虽然解决了数据表的映射问题,但是对原来已经创建的业务表并没有兼容,只好苦逼的一个个业务表处理,把多余的字段删除掉。

分析发现,如果在配置文件中加入命名策略配置后,会对整个项目全部生效,这明显不符合需求。


经过一番实验,最后找到了一种迂回的解决办法,利用多数据源的方式,具体实现如下:

1)增加Datasource配置文件

@Configuration
public class DataSourceConfig {

    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix="spring.datasource.primary")
    public DataSource dvDataSource() {
        return DataSourceBuilder.create().build();
    }

}

2)增加主数据源JPA配置文件

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactoryPrimary",
        transactionManagerRef="transactionManagerPrimary",
        basePackages= { "com.test.business" })
public class PrimaryJPAConfig {

   @Autowired
    private HibernateProperties hibernateProperties;

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource dvDataSource;

    @Primary
    @Bean(name="entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @Primary
    @Bean(name="entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        Map<String,Object> properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),new HibernateSettings());
        return builder.dataSource(dvDataSource)
                .properties(properties)
                .packages("com.test.business") //次数据源实体所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }

    @Primary
    @Bean(name="transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerDv(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

3)增加数据表使用的数据源

与主数据源配置相比,需要为数据源对应的数据源添加命名策略的配置如下

properties.put("hibernate.physical_naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");

具体配置文件如下:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactoryData",
        transactionManagerRef="transactionManagerData",
        basePackages= { "com.test.data" })
public class DataJPAConfig {

   @Autowired
    private HibernateProperties hibernateProperties;

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource dvDataSource;

    @Bean(name="entityManagerData")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryData(builder).getObject().createEntityManager();
    }

    @Bean(name="entityManagerFactoryData")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryData(EntityManagerFactoryBuilder builder) {
        Map<String,Object> properties = hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),new HibernateSettings());
        properties.put("hibernate.physical_naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
        return builder.dataSource(dvDataSource)
                .properties(properties)
                .packages("com.test.data") //次数据源实体所在位置
                .persistenceUnit("dataPersistenceUnit")
                .build();
    }

    @Bean(name="transactionManagerData")
    public PlatformTransactionManager transactionManagerData(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryData(builder).getObject());
    }
}

4)创建数据表实体类所在package

在和业务表package路径同级的位置创建数据表的package路径,在上面的代码中,业务表package为com.test.business,数据表package为com.test.data

之后所有数据表的操作都放在com.test.data路径下,这样就可以实现在不影响原有业务表的情况下,解决数据表的@Column注解不生效的问题。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
要在Spring Boot中整合Spring Data JPA,可以按照以下步骤进行操作: 1. 添加依赖:在项目的pom.xml文件中添加Spring Data JPA的依赖。可以使用以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ``` 2. 配置数据源:在Spring的配置文件中配置数据源,例如application.properties或application.yml文件。根据你使用的数据库类型,配置对应的数据源相关信息,如数据库连接URL、用户名、密码等。 3. 定义实体类:创建与数据库对应的实体类,并使用JPA注解进行映射。例如,在实体类上使用@Entity注解,指定名、字段名,以及关系映射等。 4. 创建DAO接口:创建一个继承自JpaRepository或其子接口的DAO接口。这个接口将提供一些常用的CRUD操作方法,无需手动实现。 5. 编写业务逻辑:在Service层中编写业务逻辑代码,并调用DAO接口中定义的方法进行数据访问和操作。 6. 运行程序:启动Spring Boot应用程序,Spring Boot会自动创建数据源、实体类和DAO接口的实现,并根据需要执行数据库操作。 以下是一个简单的示例: 1. 创建实体类: ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // getters and setters } ``` 2. 创建DAO接口: ```java public interface UserRepository extends JpaRepository<User, Long> { // 可以在此接口中添加自定义的查询方法 } ``` 3. 编写业务逻辑: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> getAllUsers() { return userRepository.findAll(); } public User getUserById(Long id) { return userRepository.findById(id).orElse(null); } public User saveUser(User user) { return userRepository.save(user); } public void deleteUser(Long id) { userRepository.deleteById(id); } } ``` 通过以上步骤,你就可以在Spring Boot应用程序中使用Spring Data JPA进行数据库访问和操作了。可以通过注入UserService来调用相应的方法,实现对数据库的增删改查操作。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜91

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值