0

I have this situation: I use JPA with Hibernate and I want to get some data from DB. Unfortunately I have two different sets of unique constraints. There's one on my Database Table and another one slightly different in my java Entity. I can't change one in DB because I don't have access there and I can't change one in java Entity either because it will probably generate errors in other parts of my application.

In Oracle Database I have table Foo. Inside I have two similar records:

table

My Java Entity decides if record is unique base on parameters:

  1. List item
  2. ACC_ID
  3. PLACE_ID
  4. INSTALLATION_ID
  5. DISM_DATE
  6. BOX_ID
  7. FOO_ID
  8. ACC_START_DATE

So after I execute hibernate select query based on Foo Entity I will get only one record from database (because java thinks that both foos from db are the same)

It's OK (I prefer one result), but can I somehow specify which one of these two records I will get at the end? Assume that in this case I want to get one with ACTIVITY_FLAG = 'Y' (not first from table, not random and not newest). Is this possible?

Right now I use @Embeddable and @IdClass annotations to set unique parameters in Java code:

Foo.java class:

@Entity
@Table(name = "Foo")
@IdClass(FooPK.class)

public final class Foo {

   private Long       rowId;
   private Long       boxId;
   private Integer    fooNumber;
   private String     description;
   private BigDecimal upperReadoutDate;
   private BigDecimal upperReadoutDate;
   private String     activityFlag;
   private Long       accId;
   private Long       placeId;
   private Long       installationId;
   private Date       dismountingDate;
   private Date       accStartDate;

   @Id
   @Column(name = "FOO_ID")
   public Integer getFooNumber() {
      return fooNumber;
   }

   public void setFooNumber(Integer mFooNumber) {
      fooNumber = mFooNumber;
   }

   @Column(name = "DESCRIPTION")
   public String getDescription() {
      return description;
   }

   public void setDescription(String mDescription) {
      description = mDescription;
   }

   @Column(name = "D_READ_DATE")
      public BigDecimal getLowerReadoutDate() {
      return lowerReadoutDate;
   }

   public void setLowerReadoutDate(BigDecimal mLowerReadoutDate) {
      lowerReadoutDate = mLowerReadoutDate;
   }

   @Column(name = "U_READ_DATE")
   public BigDecimal getUpperReadoutDate() {
      return upperReadoutDate;
   }

   public void setUpperReadoutDate(BigDecimal mUpperReadoutDate) {
      upperReadoutDate = mUpperReadoutDate;
   }

   @Column(name = "ACTIVITY_FLAG")
   public String getActivityFlag() {
      return activityFlag;
   }

   public void setActivityFlag(String mActivityFlag) {
      activityFlag = mActivityFlag;
   }

   @Id
   @Column(name = "BOX_ID")
   public Long getBoxId() {
      return boxId;
   }

   public void setBoxId(Long mBoxId) {
      boxId = mBoxId;
   }

   @Column(name = "ROW_ID")
   public Long getRowId() {
      return rowId;
   }

   public void setRowId(Long mRowId) {
      rowId = mRowId;
   }

   @Id
   @Column(name = "ACC_ID")
   public Long getAccId() {
      return accId;
   }

   public void setAccId(Long mAccId) {
      accId = mAccId;
   }

   @Id
   @Column(name = "PLACE_ID")
   public Long getPlaceId() {
      return placeId;
   }

   public void setPlaceId(Long mPlaceId) {
      placeId = mPlaceId;
   }

   @Id
   @Column(name = "INSTALLATION_ID")
   public Long getInstallationId() {
      return installationId;
   }

   public void setInstallationId(Long mInstallationId) {
      installationId = mInstallationId;
   }

   @Id
   @Column(name = "DISM_DATE")
   public Date getDismountingDate() {
      return dismountingDate;
   }

   public void setDismountingDate(Date mDismountingDate) {
      dismountingDate = mDismountingDate;
   }

   @Column(name = "ACC_START_DATE")
   public Date getAccStartDate() {
      return accStartDate;
   }

   public void setKuStartDate(Date mKuStartDate) {
      kuStartDate = mKuStartDate;
   }

}

FooPK.java class:

@Embeddable
public class FooPK implements Serializable {

   private static final long serialVersionUID = xxxxxxxxxxxxxxxxxxxL;
   private Long              accId;
   private Long              placeId;
   private Long              installationId;
   private Long              boxId;
   private Integer           fooNumber;
   private Date              dismountingDate;
   private Date              accStartDate;

   @Column(name = "ACC_ID")
   public Long getAccId() {
       return accId;
   }

   public void setAccId(Long mAccId) {
       accId = mAccId;
   }

   @Column(name = "PLACE_ID")
   public Long getPlaceId() {
       return placeId;
   }

   public void setPlaceId(Long mPlaceId) {
       placeId = mPlaceId;
   }

   @Column(name = "INSTALLATION_ID")
   public Long getInstallationId() {
       return installationId;
   }

   public void setInstallationId(Long mInstallationId) {
       installationId = mInstallationId;
   }

   @Column(name = "DISM_DATE")
   public Date getDismountingDate() {
       return dismountingDate;
   }

   public void setDismountingDate(Date mDismountingDate) {
       dismountingDate = mDismountingDate;
   }

   @Column(name = "BOX_ID")
   public Long getBoxId() {
       return boxId;
   }

   public void setBoxId(Long mBoxId) {
       boxId = mBoxId;
   }

   @Column(name = "FOO_ID")
   public Integer getFooNumber() {
       return fooNumber;
   }

   public void setFooNumber(Integer mFooNumber) {
       fooNumber = mFooNumber;
   }

   @Column(name = "ACC_START_DATE")
   public Date getAccStartDate() {
       return accStartDate;
   }

   public void setAccStartDate(Date mAccStartDate) {
       accStartDate = mAccStartDate;
   }

}

Thanks for any ideas!

  • Not without adding that information to the query, and for that you'd need to change the entities. Unless you are willing to write a direct SQL query and bypassing JPA. – john16384 Apr 05 '17 at 14:02
  • Have you tried writing a named query? – SME_Dev Apr 05 '17 at 14:16

1 Answers1

0

You really shouldn't define an ID for an entity such that is not unique.

JPA is a very opinionated interface between DB and Object, you either follow it or you choose another mapping / querying technique.

Updating, deleting , inserting records with a non unique ID, produces quite unpredictable results.

If ACTIVITY_FLAG is part of your unique key just add it to your @IDs.

If you cannot add the field as an @ID, add an id auto-increment field as primary key of your table.

If neither of this things are possible, you'll be better off using native SQL when dealing with that table.

I see you have a ROW_ID column as first column , if that is your primary key, just set that as @ID of your Entity.

minus
  • 2,646
  • 15
  • 18