如何在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 getUsers() { Session currentSession = sessionFactory.getCurrentSession(); return currentSession.createQuery("from User").list(); } public void insertUser(User user) { sessionFactory.getCurrentSession().save(user); } }
我得到以下exception:
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() 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() 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()
的setter中做这个
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 enttity之间的关系。 它将为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 authorities; }
角色实体: –
class UserRole{ // id and other fields. private String roleName; // Thats it !! }
- org.hibernate.HibernateException:无法解析配置:hibernate.cfg.xml
- Hibernateexception_ $$ _ javassist_0无法强制转换为javassist.util.proxy.Proxy
- 寻找一个不被弃用的会话工厂
- 使用hibernate注释导出模式
- 理解注释和JPA(hibernate)
- 处理spring + hibernateexception的地方和方式?
- 为多个模式中的实体生成Liquibase-hibernate changelog
- 使用引用列进行Hibernate一对一映射(XML映射)
- 使用Hibernate / Spring生成数据库更新脚本