休眠:通过 xml 进行多对一映射
hibernate: many-to-one mapping via xml
我遇到了一些困难,试图为两个 table 建立多对一关系:
用户和订阅者
(这里的主要思想是用户可以保存对其他用户的引用)
USERS table 包含以下字段:|USER_ID|USER_PASSWORD|
订阅者包含:|SUBSCRIBER_ID|USER_ID|,其中:
1.两个字段都包含在Primary Key中
2. 这两个字段都是从 USERS 引用 USER_ID 的外键。
将 User 保存到数据库时没有异常。
但是当我调用代码时:
(在 DB 中创建 2 个用户后 - 使用 first_u USER_ID 和 second_u USER_ID)
hibernate_session.beginTransaction();
subscr = new Subscription("first_u", "second_u");
hibernate_session.save(subscr);
hibernate_session.getTransaction().commit();
我得到这个异常:
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of player.database.hibernate.entities.User.userID
org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:64)
org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:223)
org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4601)
org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4313)
org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:276)
org.hibernate.type.EntityType.getIdentifier(EntityType.java:455)
org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:153)
org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:343)
org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:2636)
org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2604)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2883)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3386)
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access0(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
player.debugg.FriendRegistration.doGet(FriendRegistration.java:39)
player.debugg.FriendRegistration.doPost(FriendRegistration.java:20)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
java.lang.IllegalArgumentException: object is not an instance of declaring class
以下是实体 类 和 hbm.xml 的代码片段:
package player.database.hibernate.entities;
public class User
{
private String userID;
private String userPassword;
public User()
{
}
public User(String login, String password)
{
this.setUserID(login);
this.setUserPassword(password);
}
public void setUserID(String id)
{
if((id!=null)&&(!id.equals("")))
this.userID = id;
else throw new IllegalArgumentException("User ID setter exception: empty or null");
}
public void setUserPassword(String password)
{
if((password!=null)&&(!password.equals("")))
this.userPassword = password;
else throw new IllegalArgumentException("User password setter exception: empty or null");
}
public String getUserID()
{
return this.userID;
}
public String getUserPassword()
{
return this.userPassword;
}
}
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="player.database.hibernate.entities">
<class name="User" table="USERS">
<id name="userID" column="USER_ID">
<generator class="assigned"></generator>
</id>
<property name="userPassword" column="USER_PASS"/>
</class>
package player.database.hibernate.entities;
import java.io.Serializable;
public class Subscription implements Serializable
{
private String subscriberID;
private String userID;
public Subscription()
{
}
public Subscription(String subscriberID, String userID)
{
this.setSubscriberID(subscriberID);
this.setUserID(userID);
}
public void setSubscriberID(String subscriberID) {
if((subscriberID!=null)&&(!subscriberID.equals("")))
this.subscriberID = subscriberID;
else throw new IllegalArgumentException("Subscription subscriberID setter error: null or empty string");
}
public void setUserID(String userID) {
if((userID!=null)&&(!userID.equals("")))
this.userID = userID;
else throw new IllegalArgumentException("Subscription subscriberID setter error: null or empty string");
}
public String getSubscriberID() {
return subscriberID;
}
public String getUserID() {
return userID;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Subscription){
Subscription subscription = (Subscription) obj;
if(!subscription.getSubscriberID().equals(subscriberID)){
return false;
}
if(!subscription.getUserID().equals(userID)){
return false;
}
return true;
}
return false;
}
@Override
public int hashCode() {
return subscriberID.hashCode() + userID.hashCode();
}
}
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="player.database.hibernate.entities">
<class name="Subscription" table="SUBSCRIBERS">
<composite-id>
<key-many-to-one name="subscriberID" column="SUBSCRIBER_ID" class="User"/>
<key-many-to-one name="userID" column="USER_ID" class="User"/>
</composite-id>
</class>
</hibernate-mapping>
P.S。我正在使用此处描述的方式 http://www.java2s.com/Tutorial/Java/0350__Hibernate/ComposedID.htm
创建复合键。我认为它工作正常,因为它在控制台中输出 theese:
Hibernate: create table SUBSCRIBERS (SUBSCRIBER_ID varchar(255) not null, USER_ID varchar(255) not null, primary key (SUBSCRIBER_ID, USER_ID))
Hibernate: create table USERS (USER_ID varchar(255) not null, USER_PASS varchar(255), primary key (USER_ID))
Hibernate: alter table SUBSCRIBERS add constraint FKnh93vk6v0ivt3a42hbaa7ffk5 foreign key (SUBSCRIBER_ID) references USERS (USER_ID)
Hibernate: alter table SUBSCRIBERS add constraint FKodh9g832cfmbqtsgtixky9j8j foreign key (USER_ID) references USERS (USER_ID)
对于这个问题的任何帮助,我将不胜感激。
您是说订阅 class 与用户 class 具有多对一关联。我认为没有这样定义的关联。如果有关联,订阅 class 将有
private User user;
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user= user;
}
我也没有在订阅中看到任何映射 table
为了让我的代码正常工作,我将订阅 class 中的字符串字段替换为用户字段(当然还有 getter 和 setter)。我的 subscription.hbm.xml 更改为以下内容:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="player.database.hibernate.entities">
<class name="Subscription" table="SUBSCRIBERS">
<composite-id>
<key-many-to-one name="subscriberID" class="User">
<column name="SUBSCRIBER_ID" />
</key-many-to-one>
<key-many-to-one name="userID" class="User">
<column name="USER_ID" />
</key-many-to-one>
</composite-id>
</class>
</hibernate-mapping>
有了这样的配置,Hibernate 会创建如下表:
Hibernate: create table SUBSCRIBERS (SUBSCRIBER_ID varchar(255) not null, USER_ID varchar(255) not null, primary key (SUBSCRIBER_ID, USER_ID))
Hibernate: create table USERS (USER_ID varchar(255) not null, USER_PASS varchar(255), primary key (USER_ID))
Hibernate: alter table SUBSCRIBERS add constraint FKnh93vk6v0ivt3a42hbaa7ffk5 foreign key (SUBSCRIBER_ID) references USERS (USER_ID)
Hibernate: alter table SUBSCRIBERS add constraint FKodh9g832cfmbqtsgtixky9j8j foreign key (USER_ID) references USERS (USER_ID)
这正是我想要的。希望对大家有帮助。
我遇到了一些困难,试图为两个 table 建立多对一关系: 用户和订阅者
(这里的主要思想是用户可以保存对其他用户的引用)
USERS table 包含以下字段:|USER_ID|USER_PASSWORD| 订阅者包含:|SUBSCRIBER_ID|USER_ID|,其中: 1.两个字段都包含在Primary Key中 2. 这两个字段都是从 USERS 引用 USER_ID 的外键。 将 User 保存到数据库时没有异常。 但是当我调用代码时: (在 DB 中创建 2 个用户后 - 使用 first_u USER_ID 和 second_u USER_ID)
hibernate_session.beginTransaction();
subscr = new Subscription("first_u", "second_u");
hibernate_session.save(subscr);
hibernate_session.getTransaction().commit();
我得到这个异常:
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of player.database.hibernate.entities.User.userID
org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:64)
org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:223)
org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4601)
org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:4313)
org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:226)
org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:276)
org.hibernate.type.EntityType.getIdentifier(EntityType.java:455)
org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:153)
org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:343)
org.hibernate.persister.entity.AbstractEntityPersister.dehydrateId(AbstractEntityPersister.java:2636)
org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2604)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2883)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3386)
org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:89)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access0(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
player.debugg.FriendRegistration.doGet(FriendRegistration.java:39)
player.debugg.FriendRegistration.doPost(FriendRegistration.java:20)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
java.lang.IllegalArgumentException: object is not an instance of declaring class
以下是实体 类 和 hbm.xml 的代码片段:
package player.database.hibernate.entities;
public class User
{
private String userID;
private String userPassword;
public User()
{
}
public User(String login, String password)
{
this.setUserID(login);
this.setUserPassword(password);
}
public void setUserID(String id)
{
if((id!=null)&&(!id.equals("")))
this.userID = id;
else throw new IllegalArgumentException("User ID setter exception: empty or null");
}
public void setUserPassword(String password)
{
if((password!=null)&&(!password.equals("")))
this.userPassword = password;
else throw new IllegalArgumentException("User password setter exception: empty or null");
}
public String getUserID()
{
return this.userID;
}
public String getUserPassword()
{
return this.userPassword;
}
}
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="player.database.hibernate.entities">
<class name="User" table="USERS">
<id name="userID" column="USER_ID">
<generator class="assigned"></generator>
</id>
<property name="userPassword" column="USER_PASS"/>
</class>
package player.database.hibernate.entities;
import java.io.Serializable;
public class Subscription implements Serializable
{
private String subscriberID;
private String userID;
public Subscription()
{
}
public Subscription(String subscriberID, String userID)
{
this.setSubscriberID(subscriberID);
this.setUserID(userID);
}
public void setSubscriberID(String subscriberID) {
if((subscriberID!=null)&&(!subscriberID.equals("")))
this.subscriberID = subscriberID;
else throw new IllegalArgumentException("Subscription subscriberID setter error: null or empty string");
}
public void setUserID(String userID) {
if((userID!=null)&&(!userID.equals("")))
this.userID = userID;
else throw new IllegalArgumentException("Subscription subscriberID setter error: null or empty string");
}
public String getSubscriberID() {
return subscriberID;
}
public String getUserID() {
return userID;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Subscription){
Subscription subscription = (Subscription) obj;
if(!subscription.getSubscriberID().equals(subscriberID)){
return false;
}
if(!subscription.getUserID().equals(userID)){
return false;
}
return true;
}
return false;
}
@Override
public int hashCode() {
return subscriberID.hashCode() + userID.hashCode();
}
}
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="player.database.hibernate.entities">
<class name="Subscription" table="SUBSCRIBERS">
<composite-id>
<key-many-to-one name="subscriberID" column="SUBSCRIBER_ID" class="User"/>
<key-many-to-one name="userID" column="USER_ID" class="User"/>
</composite-id>
</class>
</hibernate-mapping>
P.S。我正在使用此处描述的方式 http://www.java2s.com/Tutorial/Java/0350__Hibernate/ComposedID.htm 创建复合键。我认为它工作正常,因为它在控制台中输出 theese:
Hibernate: create table SUBSCRIBERS (SUBSCRIBER_ID varchar(255) not null, USER_ID varchar(255) not null, primary key (SUBSCRIBER_ID, USER_ID))
Hibernate: create table USERS (USER_ID varchar(255) not null, USER_PASS varchar(255), primary key (USER_ID))
Hibernate: alter table SUBSCRIBERS add constraint FKnh93vk6v0ivt3a42hbaa7ffk5 foreign key (SUBSCRIBER_ID) references USERS (USER_ID)
Hibernate: alter table SUBSCRIBERS add constraint FKodh9g832cfmbqtsgtixky9j8j foreign key (USER_ID) references USERS (USER_ID)
对于这个问题的任何帮助,我将不胜感激。
您是说订阅 class 与用户 class 具有多对一关联。我认为没有这样定义的关联。如果有关联,订阅 class 将有
private User user;
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user= user;
}
我也没有在订阅中看到任何映射 table
为了让我的代码正常工作,我将订阅 class 中的字符串字段替换为用户字段(当然还有 getter 和 setter)。我的 subscription.hbm.xml 更改为以下内容:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="player.database.hibernate.entities">
<class name="Subscription" table="SUBSCRIBERS">
<composite-id>
<key-many-to-one name="subscriberID" class="User">
<column name="SUBSCRIBER_ID" />
</key-many-to-one>
<key-many-to-one name="userID" class="User">
<column name="USER_ID" />
</key-many-to-one>
</composite-id>
</class>
</hibernate-mapping>
有了这样的配置,Hibernate 会创建如下表:
Hibernate: create table SUBSCRIBERS (SUBSCRIBER_ID varchar(255) not null, USER_ID varchar(255) not null, primary key (SUBSCRIBER_ID, USER_ID))
Hibernate: create table USERS (USER_ID varchar(255) not null, USER_PASS varchar(255), primary key (USER_ID))
Hibernate: alter table SUBSCRIBERS add constraint FKnh93vk6v0ivt3a42hbaa7ffk5 foreign key (SUBSCRIBER_ID) references USERS (USER_ID)
Hibernate: alter table SUBSCRIBERS add constraint FKodh9g832cfmbqtsgtixky9j8j foreign key (USER_ID) references USERS (USER_ID)
这正是我想要的。希望对大家有帮助。