如何在hibernate中执行一对一映射插入 [英] How to perform insertion with one to one mapping in hibernate

查看:90
本文介绍了如何在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆