@Id 字段上的继承和 @AttributeOverride

2024-05-09

我有一个实体,需要手动设置 ID (PK)。 我有一些用于审计和 PK 的抽象 @MappedSuperclass,我仍然想使用它。所以我的想法是覆盖 id 列以摆脱 @GenerateValue(strategy = GenerationType.AUTO.

所以我有这样的东西:

@Entity
@Table(name = Constants.MERCHANT_PREFIX + "MERCHANT")
@Cacheable(false)
public class Merchant extends AbstractAuditable<String, Long> {
    @AttributeOverride(name = "id", column = @Column(name="ID"))
    private Long id;
    @Override
    public Long getId() {
        return id;
    }
    @Override
    public void setId(Long id) {
        this.id = id;
    }
}

@MappedSuperclass
@EntityListeners(value = { AuditingEntityListener.class })
public abstract class AbstractAuditable<U, PK extends Serializable> extends AbstractPersistable<PK> {
...
}

@MappedSuperclass
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private PK id;
    public PK getId() {
        return id;
    }
    protected void setId(final PK id) {
        this.id = id;
    }
}

它工作正常(服务器已启动并且大摇大摆)

但我的集成测试失败了,下面有这个错误。 你知道为什么吗?我想也许我不应该以这种方式使用 @AttributeOverride...而且我想找到一种工作方式,让我的 Merchant 类仍然扩展我的抽象类(审核和 PK)

org.springframework.dao.InvalidDataAccessResourceUsageException: 
could not prepare statement; 
        SQL [insert into MER_MERCHANT (ID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, ALLOW_ACCESS, id) 
values (default, ?, ?, ?, ?, ?, ?)]; 
        nested exception is org.hibernate.exception.SQLGrammarException: 
could not prepare statement

单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {ApplicationTest.class})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        DbUnitTestExecutionListener.class })
@DatabaseSetup(value = "classpath:merchantData.xml")
@DatabaseTearDown(value="classpath:merchantData.xml", type = DatabaseOperation.DELETE_ALL)
public class RestMerchantControllerTest extends AbstractControllerTest {

    @Test
    public void testCreateMerchant() throws Exception {
        final Long merchantId = 2L;
        final Boolean allowAccess = true;
        MerchantCreateVO merchantCreateVO = StubVOBuilder.buildMerchantCreateVO(allowAccess);
        String requestBody = JsonUtils.jsonFormat(merchantCreateVO);

        mvc.perform(post("/merchants/" + merchantId).contentType(MediaType.APPLICATION_JSON).content(requestBody)).andExpect(status().isOk());
    }

}

还有ApplicationTest:(ApplicationTest和我们用来设置JPA的Application很相似)

@Configuration
@ComponentScan(value = "uk.co.xxx.yyy", excludeFilters = @ComponentScan.Filter(value=Configuration.class, type = FilterType.ANNOTATION ))
@EnableWebMvc
@EnableTransactionManagement
@PropertySources({@PropertySource("classpath:hibernate.properties"), @PropertySource("classpath:junit-persistence.properties"), @PropertySource("classpath:application-test.properties")})
@EnableJpaRepositories(basePackages = "uk.co.xxx.yyy.merchant.data.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class ApplicationTest {
@Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
...
}
 @Bean
    public JpaTransactionManager transactionManager() {
...
}

}

通过服务器我得到了这个插入:

insert 
into
    MER_MERCHANT
    (CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, ALLOW_ACCESS, id) 
values
    (?, ?, ?, ?, ?, ?)

并通过集成测试:

insert 
into
    MER_MERCHANT
    (ID, CREATED_BY, CREATED_DATE, LAST_MODIFIED_BY, LAST_MODIFIED_DATE, ALLOW_ACCESS, id) 
values
    (default, ?, ?, ?, ?, ?, ?)

所以我的想法是覆盖 id 列以摆脱 @GenerateValue(策略 = GenerationType.AUTO.

@AttributeOverride 注释用于向 JPA 发出信号,表明您希望更改属性名称到列名称的默认映射。如果您正在开发一个与遗留系统进行互操作的 JPA 应用程序,而该遗留系统的字段或列的命名与您的字段或列的命名不同,则需要这样做。

从 JavaDoc 来看,@AttributeOverride 是...

  • 用于覆盖基本(无论是显式还是默认)属性或字段或 Id 属性或字段的映射。

  • 可以应用于扩展映射超类的实体或嵌入字段或属性,以覆盖由映射超类或可嵌入类(或其属性之一的可嵌入类)定义的基本映射或 id 映射。

不幸的是,此注释仅对可通过 @Column API 引用的属性或字段映射有效...并且 @Column 注释基本上允许您仅更改字段名称的映射。您无法使用 @AttributeOverride 更改字段类型或任何其他映射。因此,@GenerateValue 映射将继续被@MappedSuperclass 的所有子类继承。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

@Id 字段上的继承和 @AttributeOverride 的相关文章

随机推荐