2

さまざまな提案された解決策を試した後、私はこれを理解することができませんでした。

私はhibernate3.6とmysql5.xを使用していて、エンティティを永続化しようとしています(ゲッターとセッターを除外しました):

@Entity
@Table(name = "brand_managers")
public class BrandManager implements Serializable {

    /** Serial version unique id */
    private static final long serialVersionUID = -7992146584570782015L;

    /*--- Members ---*/

    /** The unique, internal ID of the entity. */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;

    /**
     * The creation time of this user
     */
    @Temporal(TemporalType.DATE)
    @Column(name = "creation_time")
    protected Calendar creationTime;

    /**
     * The hashed password
     */
    @Column(name = "password")
    protected String password;

    @Column(name = "first_name")
    protected String firstName;

    @Column(name = "last_name")
    protected String lastName;

    @Column(name = "email")
    protected String eMail;

    @Column(name = "address1")
    protected String address1;

    @Column(name = "address2", nullable = true)
    protected String address2;

    @Column(name = "city")
    protected String city;

    @Column(name = "state")
    protected String state;

    @Column(name = "zip", nullable = true)
    protected String zip;

    @Column(name = "country")
    protected String country;

    @Column(name = "phone")
    protected String phone;

    @Column(name = "brand_id")
    protected int brandId;

    /*--- Constructors ---*/

    /**
     * default
     */
    public BrandManager() {
    setCreationTime(Calendar.getInstance());
    }

    /**
     * @param password
     *            The hashed user password
     * @param firstName
     *            The first name
     * @param lastName
     *            The last name
     * @param eMail
     *            User eMail
     * @param address1
     *            User address
     * @param address2
     *            Another user address
     * @param city
     *            City of residence
     * @param state
     *            User state
     * @param country
     *            Country of of residence
     * @param phone
     *            User phone number
     * @param The
     *            id of the brand, managed by this brand manager
     */
    public BrandManager(String password, String firstName, String lastName, String eMail, String address1, String address2, String city,
        String state, String zip, String country, String phone, int brandId) {
    this();
    this.password = password;
    this.firstName = firstName;
    this.lastName = lastName;
    this.eMail = eMail;
    this.address1 = address1;
    this.address2 = address2;
    this.city = city;
    this.state = state;
    this.zip = zip;
    this.country = country;
    this.phone = phone;
    this.brandId = brandId;
    }

    /*--- Overridden Methods ---*/

    /**
     * Equality is based on the e-mail of this brand manager
     */
    @Override
    public boolean equals(Object obj) {

    if ((obj == null) || !(obj instanceof BrandManager)) {
        return false;
    }

    // reference comparison
    if (obj == this) {
        return true;
    }

    final BrandManager other = (BrandManager) obj;

    return new EqualsBuilder().append(geteMail(), other.geteMail()).isEquals();
    }

    /**
     * The unique hash code based on the e-mail of this brand manager
     */
    @Override
    public int hashCode() {
    return new HashCodeBuilder().append(this.geteMail()).toHashCode();
    }

    /**
     * Returning first name, last name and email.
     */
    @Override
    public String toString() {
    return ("First name: " + getFirstName() + ", Last name: " + getLastName() + ", E-Mail: " + geteMail());
    }

DBに対応するテーブルを作成しました。

CREATE TABLE `brand_managers` (
  `id` bigint(20) NOT NULL,
  `creation_time` datetime NOT NULL,
  `password` varchar(45) NOT NULL,
  `first_name` varchar(45) NOT NULL,
  `last_name` varchar(45) NOT NULL,
  `email` varchar(45) NOT NULL,
  `address1` varchar(45) NOT NULL,
  `address2` varchar(45) DEFAULT NULL,
  `city` varchar(45) NOT NULL,
  `state` varchar(45) NOT NULL,
  `zip` varchar(45) DEFAULT NULL,
  `country` varchar(45) NOT NULL,
  `phone` varchar(45) NOT NULL,
  `brand_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  UNIQUE KEY `email_UNIQUE` (`email`)

このエンティティの新しいインスタンスを永続化しようとすると、次のようになります。

2012-07-21 12:24:03 JDBCExceptionReporter [WARN] SQL Error: 1364, SQLState: HY000
2012-07-21 12:24:03 JDBCExceptionReporter [ERROR] Field 'id' doesn't have a default value
2012-07-21 12:24:03 HibernateTask [ERROR] Hibernate exception caught in me.comocomo.server.dao.objectModel.club.register.BrandManager - could not insert: [me.comocomo.server.dao.objectModel.club.register.BrandManager]
2012-07-21 12:24:03 AssertionFailure [ERROR] an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: null id in me.comocomo.server.dao.objectModel.club.register.BrandManager entry (don't flush the Session after an exception occurs)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:82)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:190)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:147)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)

これで、自動インクリメントを使用して問題を解決できました。つまり、id列(PK)を次のように変更した場合です。

ALTER TABLE `MYDB`.`brand_managers` CHANGE COLUMN `id` `id` BIGINT(20) NOT NULL AUTO_INCREMENT  ;

それはうまくいきました!

(自動インクリメントされたIDを使用して)実際にこのように動作することは問題ありませんが、これが実際に動作する唯一のコンステレーションである理由がわかりません。「IDENTITY」ジェネレーターを使用して長い型の一意のIDを生成できないのはなぜですか?

4

1 に答える 1

5

それが IDENTITY ジェネレーターです。自動インクリメント フィールドに依存して一意の ID を生成し、レコードが保存されると生成された ID をデータベースに要求するジェネレーターです。

ID をメモリ内で生成する場合は、UUID ジェネレーターを使用できます。

ほとんどのジェネレーターはデータベースに ID を生成するように要求します。これは、データベースが信頼性が高く共有されているアーキテクチャ内の唯一のコンポーネントであるためです。複数のアプリケーションがそれぞれ同じテーブルにレコードを保存し、それぞれが独自のジェネレーターを使用している場合、明らかに競合が発生します。データベースに問い合わせることで、この問題が解決されます。すべてのアプリケーションが、自動インクリメント フィールド、シーケンス、またはテーブルの使用に同意し、すべて問題ありません。

于 2012-07-21T10:01:06.003 に答える