私は冬眠するのが初めてです。私がやろうとしているのは、@CollectionId
を使用してAddressクラスの識別子を生成することです。これにはCollection
インターフェースを使用しました。ただし、@GenericGenerator
を使用して戦略をhiloに設定すると、例外がスローされます。これが私のコードです:
@Entity
@Table(name = "USER_DETAILS")
public class UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
private String userName;
@ElementCollection
@JoinTable(name="USER_ADDRESS",
joinColumns=@JoinColumn(name="USER_ID")
)
@GenericGenerator(name = "hilo-gen", strategy = "hilo")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "hilo-gen", type = @Type(type="long"))
private Collection<Address> address = new ArrayList<Address>();
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Collection<Address> getAddress() {
return address;
}
public void setAddress(List<Address> address) {
this.address = address;
}
}
次の例外が発生します。
Exception in thread "main" org.hibernate.MappingException: Could not instantiate id generator [entity-name=null]
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.createIdentifierGenerator(DefaultIdentifierGeneratorFactory.Java:121)
at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.Java:259)
at org.hibernate.persister.collection.AbstractCollectionPersister.<init>(AbstractCollectionPersister.Java:429)
at org.hibernate.persister.collection.BasicCollectionPersister.<init>(BasicCollectionPersister.Java:57)
at Sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at Sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.Java:57)
at Sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.Java:45)
at Java.lang.reflect.Constructor.newInstance(Constructor.Java:526)
at org.hibernate.persister.internal.PersisterFactoryImpl.createCollectionPersister(PersisterFactoryImpl.Java:152)
at org.hibernate.persister.internal.PersisterFactoryImpl.createCollectionPersister(PersisterFactoryImpl.Java:140)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.Java:408)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.Java:444)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:708)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:724)
at com.hbt.HibernateTest.main(HibernateTest.Java:35)
Caused by: Java.lang.UnsupportedOperationException: Support for 'hilo' generator has been removed
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.getIdentifierGeneratorClass(DefaultIdentifierGeneratorFactory.Java:132)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.createIdentifierGenerator(DefaultIdentifierGeneratorFactory.Java:112)
... 14 more
最新のHibernateを使用しています。私は何をすべきか?
Hiloはサポートされなくなりました。これは機能するはずです。
@GenericGenerator(name="sequence-gen",strategy="sequence")
Mysqlを使用している場合は、increment戦略の@ GenericGeneratorを使用することをお勧めします。
increment-この種の戦略はMySqlでサポートされています。
@ElementCollection
@JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID"))
@GenericGenerator(name = "increment-gen", strategy = "increment")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "increment-gen", type = @Type(type="long"))
private Collection<Address> listOfAddress = new ArrayList<>();
MySqlでsequence戦略を使用したときに、ADDRESS_IDが正しくインクリメントされないという問題が発生しました。
'hilo'ジェネレーターのサポートは削除されました。詳細については、このリンクから非推奨のリストを入手できます。
これを克服するには、単純にシーケンスジェネレータを使用できます。これはあなたの問題を解決します。
@Entity
@Table(name = "USER_DETAILS")
public class UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int userId;
private String userName;
@ElementCollection
@JoinTable(name="USER_ADDRESS",
joinColumns=@JoinColumn(name="USER_ID")
)
@GenericGenerator(name = "sequence-gen", strategy = "sequence")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "sequence-gen", type = @Type(type="long"))
private Collection<Address> address = new ArrayList<Address>();
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Collection<Address> getAddress() {
return address;
}
public void setAddress(List<Address> address) {
this.address = address;
}
}
以下の2つの解決策のいずれかを試してみることをお勧めします。これで問題が解決します。 Hibernate5.2.X。で提供されている仕様に従います。
情報源- https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html
ソリューション1-
@GenericGenerator(name = "product_generator",strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "product_generator", type = @Type(type="long"))*
ソリューション2-
*@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "product_generator")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "product_generator", type = @Type(type="long"))*
それがあなたを助けるかどうか私に知らせてください。
これは、PostgreSQL上のアプリで機能するものです。テストはしていませんが、すべてのDBで機能するはずです。ご了承ください increment-gen
はシーケンスではなく使用されます。
@ElementCollection
@JoinTable( name = "user_address", joinColumns = @JoinColumn( name = "user_id"))
@GenericGenerator(name="increment-gen",strategy="increment")
@CollectionId( columns = { @Column( name ="address_id") }, generator ="increment-gen", type =@Type( type ="long"))
private Collection<Address> listOfAddresses = new ArrayList<Address>();
Hi/Lo戦略の1つから選択する必要があります。
チュートリアルにできるだけ近づけるために、コードで「hilo」を「seqhilo」に変更するだけです。
参考までに、MYSQLはシーケンス戦略をサポートしていますが、テーブル名にハイフン '-'を含めることはできません(@GenericGenerator(name)で指定された名前は、mysqlでシーケンステーブルを作成するときにDDL例外を引き起こす可能性があります。