さまざまな提案された解決策を試した後、私はこれを理解することができませんでした。
私は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を生成できないのはなぜですか?