使用oneToMany关系,但在不同的时间点将数据保存在各个表中

时间:2014-10-23 13:57:22

标签: spring hibernate spring-mvc

我正在开发一个Spring-MVC应用程序,它在数据库中有2个表和2个域类。 Class Person与类Notes具有一个TOMany关系。我想在数据库中添加Person和notes。所以我用谷歌搜索,找出许多基于MVC的例子来解决同样的问题。然而,他们似乎假设了一些事情:

  1. 开发人员以静态方式添加数据,主要是通过Static void main()或其他类。
  2. 关于所有相关类的数据被完全添加,例如:表A具有oneToMany关系,因此代码将为一个类或一个jsp文件中的两个表添加数据。
  3. 其他框架如Spring-Security正在发挥作用(这一点可以理解)。
  4. 所以基本上,我找到了具有不同名称和开发人员的类似示例。我的问题是:

    1. 我没有静态void main,不打算使用它。
    2. 我通过JSP页面中包含的HTML页面添加数据。
    3. 我或者用户将首先通过注册表注册,稍后再登录然后添加注释,因此我不会同时为这两个表添加数据。 (我必须相信Hibernate可以做到这一点)
    4. 错误:

       org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.journaldev.spring.model.Person
              org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
              org.hibernate.type.EntityType.getIdentifier(EntityType.java:537)
              org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:311)
              org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:321)
              org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:294)
      

      人物模型:

      @Entity
      @Table(name="person")
      public class Person implements UserDetails{
      
          private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_USER");
      
          @Id
          @Column(name="id")
          @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "person_seq_gen")
          @SequenceGenerator(name = "person_seq_gen",sequenceName = "person_seq")
          private int id;
       @OneToMany(cascade = CascadeType.ALL,mappedBy = "person1")
        private Set<Notes> notes1;
      
          public Set<Notes> getNotes1() {
              return notes1;
          }
      
          public void setNotes1(Set<Notes> notes1) {
              this.notes1 = notes1;
          }
      

      笔记型号:

      @Entity
      @Table(name="note")
      public class Notes {
      
          @Id
          @Column(name="noteid")
          @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "note_gen")
          @SequenceGenerator(name = "note_gen",sequenceName = "note_seq")
          private int noteId;
      
       @ManyToOne
         @JoinColumn(name = "id")
         private Person person1;
      
          public Person getPerson1() {
              return person1;
          }
      
          public void setPerson1(Person person1) {
              this.person1 = person1;
          }
      

      NotesDAOImpl:

      @Transactional
      @Repository
      public class NotesDAOImpl implements NotesDAO{
      
      
      
          private SessionFactory sessionFactory;
      
          public void setSessionFactory(SessionFactory sf){
              this.sessionFactory = sf;
          }
      
      
          @Override
          public void addNote(Notes notes, int id) {
             Session session = this.sessionFactory.getCurrentSession();
             session.save(notes);
          }
      

      SQL架构:

      CREATE TABLE public.person (
                      id INTEGER NOT NULL,
                      firstname VARCHAR,
                      username VARCHAR,
                      password VARCHAR,
                      CONSTRAINT personid PRIMARY KEY (id)
      );
      
      
      CREATE TABLE public.note (
                      noteid INTEGER NOT NULL,
                      sectionid INTEGER,
                      canvasid INTEGER,
                      text VARCHAR,
                      notecolor VARCHAR,
                      noteheadline VARCHAR,
                      id INTEGER NOT NULL,
                      CONSTRAINT noteid PRIMARY KEY (noteid)
      );
      
      
      ALTER TABLE public.note ADD CONSTRAINT user_note_fk
      FOREIGN KEY (id)
      REFERENCES public.person (id)
      ON DELETE NO ACTION
      ON UPDATE NO ACTION
      NOT DEFERRABLE;
      

      顺便说一句,addNote方法中的id只是检查SpringSecurity是否实际发送了userid,并且已经正确登录,调试目的。

      所以,一旦用户登录,我无法添加备注,我做错了什么?或者Hibernate无法做到这一点。在那种情况下,让我找一把枪射击自己......:P

1 个答案:

答案 0 :(得分:1)

您的代码会尝试保存笔记。但这些笔记不会与任何人联系在一起。你必须在下面的操作顺序。

  1. 查找已登录的人员或要保存笔记的人员。
  2. 创建处于暂态状态的备注对象。
  3. 为此人附上便条。
  4. 如果是双向关系,那么请注意。
  5. 以下是代码模板。

    @Transactional
    @Repository
    public class NotesDAOImpl implements NotesDAO{
    
    
    
        private SessionFactory sessionFactory;
    
        public void setSessionFactory(SessionFactory sf){
            this.sessionFactory = sf;
        }
    
    
        @Override
        public void addNote(Notes notes, int id) {
           Session session = this.sessionFactory.getCurrentSession();
           Person person = getPerson(); // this method should get logged in person or the person for whom you want to save the notes.
           if (person.getNotes() == null) {
                Set<Note> notes = new HashSet<Note>();
                person.setNotes(notes); 
           }
           person.getNotes().add(note);
           note.setPerson(person); // If bidirectional relationship.
           session.update(person); // if update does not work, try merge();
       }
    

    还要确保在notes字段中将cascade类型设置为MERGE in person实体。

    注意:上面的代码只是代码中的示例,可能有一些编译错误。请根据您的要求更正。