【问题标题】:many to many relationship with sorting与排序的多对多关系
【发布时间】:2014-08-06 11:32:36
【问题描述】:

我正在尝试通过连接表中的附加属性在两个实体之间实现 MANY_TO_MANY 关系。 我找到了以下答案: how-to-do-a-many-to-many-relationship-in-spring-roo-with-attributes-within-de-relationship 但我未能尝试使提供的解决方案适应我的场景:

目前我有一个直接的 MANY_TO_MANY 关系:

 # book:
 entity jpa --class ~.domain.Book --testAutomatically
 field string --fieldName title --notNull
 field string --fieldName subtitle --notNull
 field string --fieldName description
 # n:m relationship to author
 field list --fieldName authors --type ~.domain.Author --cardinality MANY_TO_MANY

 # author:
 entity jpa --class ~.domain.Author --testAutomatically
 field string --fieldName firstName --notNull
 field string --fieldName lastName --notNull

按预期工作,但我需要让作者订购。我想通过定义关系表并向其中添加一个像“序列”这样的整数字段来实现这一点,但是当我尝试在 Book 中定义多对多关系时遇到了困难:

 entity jpa --class ~.domain.BookAuthorOrdered  --table book_author_ordered
 # the additional field to store sequence of authors:
 field number --fieldName authorSequence --type java.lang.Integer --notNull
 # reference to book:
 field reference --fieldName bookId --type ~.domain.Book --cardinality MANY_TO_ONE 

 # reference to author:
 field reference --fieldName authorId --type ~.domain.Author --cardinality MANY_TO_ONE

谁能给我一个提示,如何在 Book 中定义属性,以便我使用上面定义的连接表获得排序作者的列表?这是我尝试过的:

 # complete the relationship
 focus --class ~.domain.Book
 field list --type ~.domain.BookAuthorOrdered --fieldName orderedAuthors --cardinality ONE_TO_MANY --mappedBy bookId

【问题讨论】:

    标签: spring hibernate many-to-many persistence spring-roo


    【解决方案1】:

    尝试将@OrderBy 注释添加到实体字段(在.java 文件中)。举例:

       @ManyToMany
       @OrderBy("lastName ASC, firstName ASC")
       private List<Author> authors;
    

    【讨论】:

    • 嗨@jmvivo,感谢您的提示,但这不能解决我的问题。我需要在相关作者那里订购一本书。像第一作者,第二作者,...所以我需要在连接表中添加一个列来对作者与本书的关联进行排序。
    • 尝试使用 authors @Id 属性,这应该足够了(有些像 @OrderBy("authId ASC") )。
    • 也许我理解错了,但正如我之前提到的,我不需要按idauthor 表本身的任何其他属性(如firstName)对作者进行排序。我真正需要的是n:m(书作者)关联的排序。在数据库级别上,我可以通过将“排序属性”authorSequence 添加到 join 表 BookAuthorOrdered 来实现该目标。我在 8 月 14 日发布的解决方案中对此进行了描述。这对我有用,但对我来说看起来一点也不优雅。
    【解决方案2】:

    我为我的问题找到了一个或多或少可行的解决方案,但它仍然有一些缺点。它主要来自上述答案: How to do a many-to-many relationship in spring Roo, with attributes within de relationship?

    使用表 book 和 author 的 id 作为组合主键手动创建连接表: roo> entity jpa --class ~.domain.BookAuthorOrdered --table book_author_ordered --identifierType ~.domain.BookAuthorOrderedId 字段编号 --fieldName authorSequence --type java.lang.Integer --notNull

    然后编辑生成的id类BookAuthorOrderedId并添加组合主键:

    @RooToString
    @RooEquals
    @RooIdentifier
    public final class BookAuthorOrderedId {
       @ManyToOne
        @JoinColumn(name="book_id", insertable = false, updatable = false)
        private Book book;
    
       @ManyToOne
        @JoinColumn(name="author_id", insertable = false, updatable = false)
        private Author author;
    }
    

    现在是我感觉不好的部分,因为这对我来说似乎是一种解决方法。在书籍实体中,我为作者推送了 getter 方法并将其替换为连接表的查询:

       public List<Author> getAuthors()
        {
    
            // return Author.findAllAuthorsOfBook(this);
    
    
            System.out.println("getAuthors()");
            EntityManager em = new Book().entityManager;
            TypedQuery<Author> q = em.createQuery("SELECT o FROM Author AS o WHERE o.id IN ( SELECT OA.id.author FROM eu.books2ebooks.roomanova.domain.BookAuthorOrdered OA where OA.id.book = :book ) ", Author.class);
            q.setParameter("book", this);
            List<Author> authorList = q.getResultList(); 
            //this.setAuthors(authorList);
            return authorList;
        }
    

    以及一种为新添加的作者直接获取 bean 值的方法:

    public List<Author> getAddedAuthors() {
        return this.authors;
    }
    

    然后我不得不操纵 book 控制器来调用一个自写的方法来插入/更新连接表(在 create/update/..):

    public static void setOrderedBookAuthors(Book book, List<Author> authors) {
        // delete all associated authors of book:
        List<BookAuthorOrdered> bookAuthorOrdereds = BookAuthorOrdered.findAllBookAuthorOrdersOfBook(book);
        for (BookAuthorOrdered bookAuthorOrdered : bookAuthorOrdereds) {
            log.info("removing book author: " + printAuthor(bookAuthorOrdered.getId().getAuthor()));
            bookAuthorOrdered.remove();
        }
        if ( authors == null )
        {
            log.info("ordered authors: null. nothing to insert.");
            return;
        }
        log.info("inserting sorted authors: ");
        Integer authorSequence = 1;
        for (Author author : authors) {
            log.info("inserting book author sorted: " + printAuthor(author) + " as no " + authorSequence);
            BookAuthorOrdered bookAuthorOrdered = new BookAuthorOrdered();
            bookAuthorOrdered.setAuthorSequence(authorSequence);
            BookAuthorOrderedId id = new BookAuthorOrderedId(book, author);
            bookAuthorOrdered.setId(id);
            log.info("book author ordered: " + bookAuthorOrdered);
            bookAuthorOrdered.persist();
    
            authorSequence++;
        }
    }
    

    到目前为止,这是可行的,但感觉必须有一种更优雅的方式......

    【讨论】:

      猜你喜欢
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 2016-04-07
      • 2011-08-23
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多