簡體   English   中英

如何在休眠中使用一對一映射執行插入

[英]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 keyUser 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM