[英]How to perform insertion with one to one mapping in hibernate
我已經成功創建了兩個實體之間的一對一映射。 我能夠從兩個表中檢索數據,但是我無法執行插入操作。
@Entity
@Table(name="users_test")
public class User {
@Id
@Column(name="user_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String username;
private String password;
private int enabled;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private UserRole userRole;
//getters and setters
}
@Entity
@Table(name = "user_roles")
public class UserRole {
private int user_role_id;
@Id
@GeneratedValue(generator = "gen")
@Column(name = "user_id", unique = true, nullable = false)
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="user"))
private int user_id;
private String authority;
@OneToOne(mappedBy="userRole", cascade=CascadeType.ALL)
private User user;
//getters and setters
}
我可以通過此映射從表中成功讀取值,但是當我嘗試將數據插入表中時出現錯誤。
public class Runner {
public static void main(String[] args) {
Runner run = new Runner();
ApplicationContext context = new FileSystemXmlApplicationContext("E:\\applicationContext.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
UserRole userRole = new UserRole();
userRole.setAuthority("USER_ROLE");
userRole.setUser_role_id(0);
User user = new User();
user.setUsername("ichigo");
user.setPassword("kura");
user.setEnabled(0);
user.setUserRole(userRole);
userDao.insertUser(user);
}
}
UserDao:
@SuppressWarnings("unchecked")
@Repository
@Transactional
public class UserDao {
@Autowired
SessionFactory sessionFactory;
public List<User> getUsers() {
Session currentSession = sessionFactory.getCurrentSession();
return currentSession.createQuery("from User").list();
}
public void insertUser(User user) {
sessionFactory.getCurrentSession().save(user);
}
}
我得到以下異常:
Exception in thread "main" org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [test.hibernate.model.UserRole.user]
at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:101)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:118)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:724)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:716)
at org.hibernate.engine.spi.CascadingAction$5.cascade(CascadingAction.java:258)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:448)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:753)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:745)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:741)
at test.hibernate.dao.UserDao.insertUser(UserDao.java:24)
at test.hibernate.dao.UserDao$$FastClassByCGLIB$$192f03a.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at test.hibernate.dao.UserDao$$EnhancerByCGLIB$$7428e072.insertUser(<generated>)
at test.hibernate.test.main.Runner.main(Runner.java:34)
請建議我做錯了什么。
編輯:
從答復看來,我在代碼中混合了我的外鍵。 因此,只需將問題弄清楚,我將發布表的架構。
CREATE TABLE `users_test` (
`USER_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`USERNAME` varchar(45) NOT NULL,
`PASSWORD` varchar(45) NOT NULL,
`ENABLED` tinyint(1) NOT NULL,
PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=113 DEFAULT CHARSET=utf8
CREATE TABLE `user_roles` (
`USER_ROLE_ID` int(10) DEFAULT NULL,
`USER_ID` int(10) unsigned NOT NULL,
`AUTHORITY` varchar(45) NOT NULL,
PRIMARY KEY (`USER_ID`),
KEY `FK_user_roles` (`USER_ID`),
CONSTRAINT `FK_user_roles` FOREIGN KEY (`USER_ID`) REFERENCES `users_test` (`USER_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
您的一對一映射也有誤,外鍵使用不正確。 在您的示例中,外鍵使用錯誤。 您的映射顯示UserRole
primary key
是User
foreign key
,但不是。 您需要刪除@PrimaryKeyJoinColumn
並使用@JoinColumn
映射外鍵
有兩種類型的一對一映射。
單向映射
只有對象的欠側才被映射為關系。 對象沒有出現在關系的另一端。
@Entity
@Table(name="users_test")
public class User {
@Id
@Column(name="user_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String username;
private String password;
private int enabled;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
private UserRole userRole;
//getters and setters
}
由於使用了雙向映射,因此UserRole
類將沒有任何User
。
@Entity
@Table(name = "user_roles")
public class UserRole {
@Id
@GeneratedValue(generator = "gen")
@Column(name = "user_role_id", unique = true, nullable = false)
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="user"))
private int user_role_id;
private String authority;
}
雙向映射
這兩個類都具有這種映射樣式的關系。 這里使用的mappedBy
屬性強調關系的mappedBy
。 不需要第二個外鍵,只需將User
對象添加到具有正確映射的UserRole
。 在您的情況下,它是由user
而不是userRole
映射的。
@Entity
@Table(name = "user_roles")
public class UserRole {
@Id
@GeneratedValue(generator = "gen")
@Column(name = "user_role_id", unique = true, nullable = false)
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="user"))
private int user_role_id;
private String authority;
@OneToOne(mappedBy="user", cascade=CascadeType.ALL)
private User user;
//getters and setters
}
編輯
還有另一個錯誤的映射。 UserRole#user_role_id
是您的外鍵,並用@Id
注釋。
您具有雙向關系,但僅設置關系船的一側。 您只在做user.setUserRole(userRole)
。 您需要執行一個userRole.setUser(user)
,我更喜歡在setUserRole()
的設置器中執行此操作
public clas User {
public void setUserRole(UserRole userRole) {
this.userRole=userRole;
this.userRole.setUserRole(this);
}
}
這樣總是可以處理的。 (您可能還需要/想要添加一個null
檢查)。
代碼中還有一件奇怪的事情,為什么您的UserRole
對象有一個User
和一個user_id
字段? 恕我直言,它應該只有一個User
字段。
@Entity
@Table(name = "user_roles")
public class UserRole {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int user_role_id;
private String authority;
@OneToOne(mappedBy="user", cascade=CascadeType.ALL)
private User user;
//getters and setters
}
我希望有類似上面的東西。
首先,根據我的理解,用戶和角色實體之間的一對一映射是不正確的。 您可能希望您的用戶擁有多個角色,對嗎?
UserRole實體不應具有對User的引用-UserRole在沒有User的情況下可以存在。
一個用戶可以具有多個角色,並且一個角色可以分配給多個用戶。 (假設這是您打算做的。)
我建議您使用User&UserRole實體之間的單向多對多關系。 它將為User-UserRole映射創建一個單獨的表。
例:-
class User {
// ID and other fields
@ManyToMany(fetch = FetchType.EAGER)
@JoinColumn(unique = false, nullable = false, name = "ROLE", insertable = true)
@Fetch(value = FetchMode.JOIN)
@JoinTable(name="USER_ROLE_MAPPING")
private List<UserRole> authorities;
}
角色實體:
class UserRole{
// id and other fields.
private String roleName; // Thats it !!
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.