主键问题

因为在Oracle数据库中,容许没有主键的存在,而hibernate体系又不容许没有主键,这在逻辑上是有冲突的。事实上,表不须要主键。表没有显式键对数据库没有任何影响,由于数据库中的每一行都有一个隐式的惟一数据点,Oracle将其用于存储和某些内部引用,即rowid伪列。rowid是惟一标识数据库中每一行的一段数据。严格来讲,没有必要把钥匙放在桌子上。好比如今的项目中,使用的oracle10g数据库有超过1000个系统表,它们没有主键或者说在各自的表上有惟一键。dba和开发人员均可以决定如何在数据库表上建立密钥。然而在开发过程当中老是建立主键,这个估计是开发框架致使的,而框架才无论它们是否有用或健全。但做为优秀dba,他们只在有意义的地方建立键。
不少时候线上和线下开发是彻底隔离开的,线下开发后的测试环境也不可能那么完美的贴合生产环境,笔者的项目中所使用数据库为marridb,而生产环境中使用的数据库为Oracle,这个联调过程当中产生的bug也真的是不可多得:),我这边获取到测试数据确实是来自生产环境,然而这个是经过select语句而来的,这就直接致使这个表是没有主键的。以后把这些测试数据导入到marridb。java

如今的状况就是数据库一个没有主键的表,然而经过springboot所建立实体却要求配置主键,这跟数据库中的配置不相符,此外因为实体类中所定义的主键,在数据库中重复出现。spring

主键问题

这其实是违背了数据库中主键的定义惟一地标识表中的每一行,经过它可强制表的实体完整性,致使出现这样表的缘由是,在Oracle中容许没有主键的定义,经过多表联查汇总到一张表中,而后将这张表导入到marridb中,才会出现这么尴尬的结果数据库

主键问题

致使的结果就是搜索到某一个uuid,其结果有17条,经过jpa取结果整个list长度确实为17,然而,数据展开以后会发现,里面几乎都是重复数据express

2019-12-09 19:39:20.411  WARN 26340 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bussiness' defined in file [/xxx/yyy/zzz/service/Bussiness.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'alarmStatisticServiceImpl' defined in file [xxx/yyy/zzz/service/impl/AlarmStatisticServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processAccountRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List xxx.yyy.zzz.repository.ProcessAccountRepository.getAllData()!

没法建立一个bean,而其实是因为某一类是未指定标识符的实体,主要缘由是hibernate在进行扫描实体的时候,未发现其主键标识。因此就在其类上添加主键标识。由于个人这个类比较特殊,须要添加联合主键springboot

联合主键用Hibernate注解映射方式主要有三种:oracle

  1. 将联合主键的字段单独放在一个类中,该类须要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为@Embeddable,最后在主类中(该类不包含联合主键类中的字段)保存该联合主键类的一个引用,并生成set和get方法,以后将该引用注解为@Id
  框架

@Entity
@Table(name = "Process_Account")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ProcessAccount {

    @Id
    private ProcessAccountPk priAccountpk;
}

  
主键类:  ide

@Embeddable
public class ProcessAccountPk implements Serializable {
    @Column(name = "UUID")
    private String uuid;

    @Column(name = "xxx")
    private String priAccount;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ProcessAccountPk)) return false;
        ProcessAccountPk that = (ProcessAccountPk) o;
        return Objects.equals(getUuid(), that.getUuid()) &&
            Objects.equals(getPriAccount(), that.getPriAccount());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUuid(), getPriAccount());
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getPriAccount() {
        return priAccount;
    }

    public void setPriAccount(String priAccount) {
        this.priAccount = priAccount;
    }
}
  1. 将联合主键的字段单独放在一个类中,该类须要实现java.io.Serializable接口并重写equals和hascode,最后在主类中(该类不包含联合主键类中的字段)保存该联合主键类的一个引用,并生成set和get方法,并将该引用注解为@EmbeddedId
@Entity  
@Table(name="Process_Account")  
public class ProcessAccount {  

    @Id
    @Column(name = "RESUUID")
    private String uuid;

    @Id
    @Column(name = "xxx")
    private String priAccount; 
    @EmbeddedId
    private ProcessAccountPk processAccountPk ;
}

  这个时候ProcessAccountPk为普通Java类便可。测试

  3、将联合主键的字段单独放在一个类中,该类须要实现java.io.Serializable接口并要重写equals和hashcode.最后在主类中(该类包含联合主键类中的字段)将联合主键字段都注解为@Id,并在该类上方将上这样的注解:@IdClass(联合主键类.class),通过踩坑,我用了这个方法:),中间的判断过程就一笔带过吧,有问题私聊ui

@Entity
@Table(name = "Process_Account")
@IdClass(ProcessAccountPk.class)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ProcessAccount {

    @Id
    @Column(name = "RESUUID")
    private String uuid;

    @Id
    @Column(name = "xxx")
    private String priAccount;
}

ProcessAccountPk 继承自Serializable类

public class ProcessAccountPk implements Serializable {

    private String uuid;

    private String priAccount;

    public ProcessAccountPk() {
    }

    public ProcessAccountPk(String uuid, String priAccount) {
        this.uuid = uuid;
        this.priAccount = priAccount;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof ProcessAccountPk)) return false;
        ProcessAccountPk that = (ProcessAccountPk) o;
        return Objects.equals(getUuid(), that.getUuid()) &&
            Objects.equals(getPriAccount(), that.getPriAccount());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getUuid(), getPriAccount());
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getPriAccount() {
        return priAccount;
    }

    public void setPriAccount(String priAccount) {
        this.priAccount = priAccount;
    }
}

主键问题

主键问题

至此,问题解决了,我取出来的数据不会因为uuid或者bussinessName致使数据重复,两个字段同时做为主键进行查询就能够解决这个问题

相关文章
相关标签/搜索