如何在hibernate中执行一对一映射插入 [英] 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 int;
@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 = @参数(name =property,value =user))
private int user_id;
私有字符串权限;
@OneToOne(mappedBy =userRole,cascade = CascadeType.ALL)
私人用户用户;
// getters and setters
}
我成功能够通过此映射从表中读取值,但是当我尝试向表中插入数据时出现错误。
public class Runner {
public static void main(String [] args){
Runner run =新亚军();
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
公共类UserDao {
@Autowired
SessionFactory sessionFactory;
公共列表<用户> getUsers(){
Session currentSession = sessionFactory.getCurrentSession();
return currentSession.createQuery(from User)。list();
}
public void insertUser(User user){
sessionFactory.getCurrentSession()。save(user);
}
}
我收到以下异常:
线程main中的异常org.hibernate.id.IdentifierGenerationException:试图从null一对一属性[test.hibernate。 model.UserRole.user]在org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:101)
。在org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:118)
,位于org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSave orUpdateEventListener.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)
在org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208)
在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)
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
at org.hiberna te.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
位于org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
位于org.hibernate.event处。 internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
位于org.hibernate.event.internal.DefaultSaveEventListener。 performSaveOrUpdate(DefaultSaveEventListener.java:49)
在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
在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)维持在org.springframework org.springframework.aop.framework.Cglib2AopProxy $ CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
。 aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
处org.springframework.aop.framework org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
。 ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
在org.springframework.aop.framework.Cglib2AopProxy $ DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
在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
的主键
是外键
在用户
中,但它不是。您需要删除 @PrimaryKeyJoinColumn
并将外键映射到 @JoinColumn
有2种类型的一对一映射。
单向映射
只有对象的欠缺一方被映射到关系中。对象不出现在关系的另一端。
@Entity
@Table(name =users_test)
public class User {
@Id
@Column(name =user_id)
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
私人字符串用户名;
私人字符串密码;
启用private int;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name =user_id)
private UserRole userRole;
// getters and setters
}
和<$因为使用了双向映射,所以c $ c> UserRole 类将不会有任何 User
。
< pre $ @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 = @参数(name =property,value =user))
private int user_role_id;
私有字符串权限;
$ b
双向映射
这两个类在这种映射风格中都有关系。 mappedBy
属性用于强调关系的欠方面。不需要第二个外键,只需将 User
对象添加到 UserRole
中即可。它由用户
而不是 userRole
进行映射。
< pre $
@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 = @参数(name =property,value =user))
private int user_role_id;
私有字符串权限;
@OneToOne(mappedBy =user,cascade = CascadeType.ALL)
private用户用户;
// getters and setters
}
编辑
还有一个错误的映射。 UserRole#user_role_id
是用 @Id
注释的外键。
I have successfully created a one-to-one mapping between two entities. I am able to retrieve data from the two tables, however I am failing to perform an insertion.
@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
}
I was successfully able to read values from the tables via this mapping, however when I try to insert data into the tables I get an error.
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);
}
}
I get the following 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(<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)
Please advice on what am I doing wrong.
EDIT:
It seems from the replies that I have my foreign keys mixed up in the code. So just make the question clear, I am posting the schema of the tables.
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
Your one to one mapping is also wrong, foreign key are not used properly. In your example, there is wrong usage of foreign keys. Your mapping says that primary key
of UserRole
is foreign key
in User
, but it is not. You need to remove @PrimaryKeyJoinColumn
and map foreign key with @JoinColumn
There are 2 types of one to one mapping.
Unidirectional Mapping
Only owing side of the object is mapped in relations. Object is not appear in the other side of relation.
@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
}
And UserRole
class will not have any User
since bidirectional mapping is used.
@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;
}
Bidirectional Mapping
Both classes have the relations in this mapping style. mappedBy
attribute used here to emphasize owing side of the relation. There no need second foreign key, just add User
object to UserRole
with proper mapping. It is mapped by user
not userRole
in your case.
@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
}
Edit
There is another wrong mapping. UserRole#user_role_id
is your foreign key which is annotated with @Id
.
这篇关于如何在hibernate中执行一对一映射插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!