2010-12-15 14 views
6

1つのシーケンスと2つの外部キーからなる複合主キーを持つテーブルがあります 私のエンティティクラスは永続化できますが、シーケンスに従って生成されません。 Mavenの中hbm2javaは、ここで次のエンティティにJPA @EmbeddedIdがシーケンスを生成していません

を与え、一つの配列と2つの外部キーから成る複合主キーを持つテーブルは、ここでの主なエンティティ

 

package aop.web.teacher.rmodels; 

// Generated Dec 14, 2010 8:45:32 PM by Hibernate Tools 3.2.2.GA 

import java.util.Date; 
import javax.persistence.AttributeOverride; 
import javax.persistence.AttributeOverrides; 
import javax.persistence.Column; 
import javax.persistence.EmbeddedId; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 
import javax.persistence.Temporal; 
import javax.persistence.TemporalType; 

/** 
* Schoolmaster generated by hbm2java 
*/ 
@Entity 
@Table(name = "schoolmaster", schema = "public") 
public class Schoolmaster implements java.io.Serializable { 

private SchoolmasterId id; 
     ... 


@EmbeddedId 
@AttributeOverrides({ 
    @AttributeOverride(name = "id", column = @Column(name = "id", nullable = false)), 
    @AttributeOverride(name = "districtId", column = @Column(name = "district_id", nullable = false)), 
    @AttributeOverride(name = "typeOfSchool", column = @Column(name = "type_of_school", nullable = false)) }) 
public SchoolmasterId getId() { 
    return this.id; 
} 

public void setId(SchoolmasterId id) { 
    this.id = id; 
} 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "type_of_school", nullable = false, insertable = false, updatable = false) 
public AopTeachersTypeMaster getAopTeachersTypeMaster() { 
    return this.aopTeachersTypeMaster; 
} 

public void setAopTeachersTypeMaster(
    AopTeachersTypeMaster aopTeachersTypeMaster) { 
    this.aopTeachersTypeMaster = aopTeachersTypeMaster; 
} 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "school_nature") 
public AopTeachersSchoolNatureMaster getAopTeachersSchoolNatureMaster() { 
    return this.aopTeachersSchoolNatureMaster; 
} 

public void setAopTeachersSchoolNatureMaster(
    AopTeachersSchoolNatureMaster aopTeachersSchoolNatureMaster) { 
    this.aopTeachersSchoolNatureMaster = aopTeachersSchoolNatureMaster; 
} 

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "district_id", nullable = false, insertable = false, updatable = false) 
public AopTeachersDistrictMaster getAopTeachersDistrictMaster() { 
    return this.aopTeachersDistrictMaster; 
} 

public void setAopTeachersDistrictMaster(
    AopTeachersDistrictMaster aopTeachersDistrictMaster) { 
    this.aopTeachersDistrictMaster = aopTeachersDistrictMaster; 
} 

@Column(name = "school_name", length = 50) 
public String getSchoolName() { 
    return this.schoolName; 
} 

public void setSchoolName(String schoolName) { 
    this.schoolName = schoolName; 
} 

@Column(name = "school_address") 
public String getSchoolAddress() { 
    return this.schoolAddress; 
} 

public void setSchoolAddress(String schoolAddress) { 
    this.schoolAddress = schoolAddress; 
} 

@Column(name = "school_phone_number", length = 12) 
public String getSchoolPhoneNumber() { 
    return this.schoolPhoneNumber; 
} 

public void setSchoolPhoneNumber(String schoolPhoneNumber) { 
    this.schoolPhoneNumber = schoolPhoneNumber; 
} 

@Temporal(TemporalType.DATE) 
@Column(name = "establishment_date", length = 13) 
public Date getEstablishmentDate() { 
    return this.establishmentDate; 
} 

public void setEstablishmentDate(Date establishmentDate) { 
    this.establishmentDate = establishmentDate; 
} 

@Column(name = "school_no_of_teachers") 
public Integer getSchoolNoOfTeachers() { 
    return this.schoolNoOfTeachers; 
} 

public void setSchoolNoOfTeachers(Integer schoolNoOfTeachers) { 
    this.schoolNoOfTeachers = schoolNoOfTeachers; 
} 

@Column(name = "school_no_of_students") 
public Integer getSchoolNoOfStudents() { 
    return this.schoolNoOfStudents; 
} 

public void setSchoolNoOfStudents(Integer schoolNoOfStudents) { 
    this.schoolNoOfStudents = schoolNoOfStudents; 
} 

} 

 

は、埋め込まれたPKクラスです。ここで私はIdが自動生成されるように期待してい

 

/** 
* SchoolmasterId generated by hbm2java 
*/ 
@Embeddable 
public class SchoolmasterId implements java.io.Serializable { 


    private long id; 
    private long districtId; 
    private long typeOfSchool; 

    public SchoolmasterId() { 
    } 

    public SchoolmasterId(long id, long districtId, long typeOfSchool) { 
     this.id = id; 
     this.districtId = districtId; 
     this.typeOfSchool = typeOfSchool; 
    } 


    @Column(name="id", nullable=false) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE) 
    public long getId() { 
     return this.id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    @NaturalId 
    @Column(name="district_id", nullable=false) 
    public long getDistrictId() { 
     return this.districtId; 
    } 

    public void setDistrictId(long districtId) { 
     this.districtId = districtId; 
    } 
    @NaturalId 
    @Column(name="type_of_school", nullable=false) 
    public long getTypeOfSchool() { 
     return this.typeOfSchool; 
    } 

    public void setTypeOfSchool(long typeOfSchool) { 
     this.typeOfSchool = typeOfSchool; 
    } 


    public boolean equals(Object other) { 
     if ((this == other)) return true; 
    if ((other == null)) return false; 
    if (!(other instanceof SchoolmasterId)) return false; 
    SchoolmasterId castOther = (SchoolmasterId) other; 

    return (this.getId()==castOther.getId()) 
&& (this.getDistrictId()==castOther.getDistrictId()) 
&& (this.getTypeOfSchool()==castOther.getTypeOfSchool()); 
    } 

    public int hashCode() { 
     int result = 17; 

     result = 37 * result + (int) this.getId(); 
     result = 37 * result + (int) this.getDistrictId(); 
     result = 37 * result + (int) this.getTypeOfSchool(); 
     return result; 
    } 


} 

 

... は私だけ私もGenerationType.AUTO と試みたが、やっている

 

@NaturalId 
 

 

@GeneratedValue(strategy=GenerationType.SEQUENCE) 
 

を追加しましたうまくいかない。 お勧めします。

+0

答えることができないからです。私は同様のユースケース(3つのうち1つの主キーフィールドが自動生成されている(PostgreSQLのbigserial))を持っており、@ GeneratedValueは@Idと一緒にしか使用できないことを発見しました。 –

+1

私はそれについて尋ねた投稿の量を考えると、それができないことは驚くべきことです。私は多少の共通のユースケースを提供したくないhibernate/jpa/eclipselink開発者の面倒を見ています。 「私たちはよく知っている」態度の一つです。 – BillR

答えて

6

この問題の回避策が1つあります。私は同じ条件に直面しており、4つのフィールドを合成キーとして持っています。そのうちの1つはシーケンスによって生成する必要があります。 私はEmbeddedクラスを全く作成していませんが、シーケンスで生成する必要がある@Idフィールドしかありません。残りのすべてのフィールド値は単純な列になります。参照整合性がDBに適用され、コード内の残りの3つのフィールドの値がNULLでないことを確認しています。

エラーの場合、トランザクションはロールバックされます。

0

私の2cを追加したいだけです。これは複合キーと単一の主キーで機能します。シーケンスを作成する代わりに、テーブルからmax + 1を選択します。

Identifiable.java

package my.app.hibernate; 

import java.io.Serializable; 

public interface Identifiable<T extends Serializable> { 
    T getId(); 
} 

CompositeKeyEntity.java

package my.app.hibernate; 

import java.io.Serializable; 

public interface CompositeKeyEntity<T extends Serializable> extends Identifiable<T> { 
} 

SingleKeyEntity.java

package my.app.hibernate; 

import java.io.Serializable; 

public interface SingleKeyEntity<T extends Serializable> extends Identifiable<T> { 
} 

AssignedIdentityGenerator.java

package my.app.hibernate; 

import java.io.Serializable; 
import java.lang.reflect.Field; 
import java.util.Arrays; 
import java.util.List; 

import org.hibernate.Criteria; 
import org.hibernate.criterion.Projections; 
import org.hibernate.criterion.Restrictions; 
import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.id.IdentityGenerator; 
import org.hibernate.internal.CriteriaImpl; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.security.util.FieldUtils; 

public class AssignedIdentityGenerator extends IdentityGenerator { 
    private static final String ID_FIELD_NAME = "id"; 
    private final Logger LOG = LoggerFactory.getLogger(this.getClass()); 
    private Field sequenceField; 
    private String entityClassName; 

    @Override 
    public Serializable generate(SessionImplementor session, Object obj) { 
     @SuppressWarnings("unchecked") 
     Identifiable<Serializable> identifiable = (Identifiable<Serializable>)obj; 

     entityClassName = obj.getClass().getName(); 
     Criteria criteria = new CriteriaImpl(entityClassName, session); 
     criteria.setReadOnly(true); 
     Object toSet = null; 

     if (identifiable instanceof CompositeKeyEntity) { 
      Serializable id = identifiable.getId(); 
      if (id != null) { 
       String embaddebleClassName = id.getClass().getName(); 
       buildCriteriaForEmbeddedId(id, embaddebleClassName, criteria); 
       toSet = id; 
      } 
     } else if (obj instanceof SingleKeyEntity) { 
      toSet = identifiable; 
      sequenceField = FieldUtils.getField(identifiable.getClass(), ID_FIELD_NAME); 
      buildCriteriaForSingleId(criteria); 
     } 

     Number one = castToSequenceNumberType(1L); 
     Number value = (Number) criteria.uniqueResult(); 

     if(value != null) { 
      value = castToSequenceNumberType(value.longValue() + one.longValue()); 

      setFieldValue(sequenceField, value, toSet); 
     } else { 
      value = one; 
      setFieldValue(sequenceField, value, toSet); 
     } 

     return identifiable.getId(); 
    } 

    private void buildCriteriaForSingleId(Criteria criteria) { 
     criteria.setProjection(Projections.max(ID_FIELD_NAME).as("seq")); 
    } 

    private void buildCriteriaForEmbeddedId(Serializable id, String embaddebleClassName, Criteria criteria) { 
     List<Field> fields = Arrays.asList(id.getClass().getDeclaredFields()); 

     class Utils { 
      Field field; 
      boolean numberFound = false; 
     } 
     final Utils utils = new Utils(); 

     for (Field field : fields) { 
      if ("serialVersionUID".equals(field.getName()) || "$jacocoData".equals(field.getName())) { 
       continue; 
      } 

      if (Number.class.isAssignableFrom(field.getType())) { 
       if (utils.numberFound) { 
        throw new IllegalArgumentException(
          embaddebleClassName + " has more then one sequence field: " + field.getName() + ", " 
            + utils.field.getName() + ",..."); 
       } 

       utils.numberFound = true; 
       utils.field = field; 
       sequenceField = field; 

       criteria.setProjection(Projections.max(ID_FIELD_NAME + "." + sequenceField.getName()).as("seq")); 
      } else { 
       criteria.add(Restrictions.eq(ID_FIELD_NAME + "." + field.getName(), getFieldValue(field, id))); 
      } 
     } 
    } 

    private Number castToSequenceNumberType(Number n) { 
     return (Number) sequenceField.getType().cast(n); 
    } 

    private void setFieldValue(Field field, Object value, Object to) { 
     try { 
      field.setAccessible(true); 
      field.set(to, value); 
     } catch (IllegalArgumentException | IllegalAccessException e) { 
      LOG.error(e.getMessage(), e); 
     } 
    } 

    private Object getFieldValue(Field field, Object from) { 
     try { 
      field.setAccessible(true); 
      return field.get(from); 
     } catch (IllegalArgumentException | IllegalAccessException e) { 
      LOG.error(e.getMessage(), e); 
     } 

     return null; 
    } 
} 

私はあなたが受け取っていない疑いがあるCustomer.java

package my.app.entities; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import org.hibernate.annotations.GenericGenerator; 

import my.app.hibernate.SingleKeyEntity; 

@Entity(name = "whatever_entity_name") 
@GenericGenerator(name = "WHATEVER_NAMED_GENERATOR", strategy = "my.app.hibernate.AssignedIdentityGenerator") 
public class Customer implements SingleKeyEntity<Long> { 

    @Id 
    @GeneratedValue(generator = "WHATEVER_NAMED_GENERATOR") 
    private Long id; 
    @Column(nullable = false) 
    private String name; 
} 

CustomerItemsId.java(それはSingleKeyEntityの例を次のようにItem.javaがommited)

package my.app.entities; 

import javax.persistence.Embeddable; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 

@Embeddable 
public class CustomerItemsId implements Serializable { 
    private static final long serialVersionUID = 1L; //generate one 

    @ManyToOne 
    @JoinColumn(name = "customer_id") 
    private Customer customer; 
    @ManyToOne 
    @JoinColumn(name = "item_id") 
    private Item item; 
    private Long seq; //name as you wish 
} 

CustomerItems.java

package my.app.entities; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import org.hibernate.annotations.GenericGenerator; 

import my.app.hibernate.CompositeKeyEntity; 

@Entity(name = "whatever_entity_name") 
@GenericGenerator(name = "WHATEVER_NAMED_GENERATOR", strategy = "my.app.hibernate.AssignedIdentityGenerator") 
public class CustomerItems implements CompositeKeyEntity<CustomerItemsId> { 

    @GeneratedValue(generator = "WHATEVER_NAMED_GENERATOR") 
    private CustomerItems id; 
    @Column(nullable = false) 
    private String randomColumn1; 
    @Column(nullable = false) 
    private String randomColumn2; 
} 
関連する問題