简体   繁体   中英

Many-To-Many extra columns Spring JPA

Has passed a week and I'm struggling with a problem and it seems that I'm not able to find any answer to it.

I have this structure: 数据库结构

Album model:

@Entity
@Table(name = DatabaseConstants.ALBUM_TABLE_NAME)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Album {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 100)
    private String name;

    @Column(nullable = false)
    private int imageVersion = 1;

    @Column(length = 255)
    private String description;

    @Column(nullable = false)
    private boolean single = false;

    @Column(nullable = false)
    private Long createdAt;

    @Column(nullable = true)
    private Long deletedAt;

    // Relations

    @OneToMany(fetch = FetchType.LAZY)
    private List<AlbumView> albumViews;

    // Getters and Setters
}

AlbumView model:

@Entity
@Table(name = DatabaseConstants.ALBUM_VIEW_RELATION_TABLE_NAME)
public class AlbumView {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private boolean bigger;

    @Column(nullable = false)
    private int position;

    @Column(nullable = false)
    private Long createdAt;

    @Column(nullable = true)
    private Long deletedAt;

    // Relations

    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "album_id")
    private Album album;

    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "view_id")
    private View view;

    // Getters and Setters    
}

View model:

@Entity
@Table(name = DatabaseConstants.VIEW_TABLE_NAME)
public class View {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Long createdAt;

    @Column(nullable = true)
    private Long deletedAt;

    // Relations

    @OneToMany(fetch = FetchType.LAZY)
    private List<AlbumView> albumViewList;

    // Getters and Setters
}

I need to search a list of albums by an view. I that the query that I need is something like (Using @Query annotation from Spring JPA):

SELECT a, av.bigger, av.position FROM Album a, AlbumView av WHERE av.view.id = ?    

But I can't map those two values (bigger, position) because they aren't on the Album model. I need to build an response like:

[
    {
        id: 1,
        name: 'Test Album',
        imageVersion: 1,
        description: 'Description one',
        single: true,
        bigger: true,
        position: 1
    },
    {
        id: 2,
        name: 'Test Album 2',
        imageVersion: 1,
        description: 'Description two',
        single: true,
        bigger: false,
        position: 2
    }
]

As far as I read, I can't use @Transient to help me here (because apparently JPA ignores it and the @Query don't fill those attributes) and I don't know other way to do it. Thanks.

EDIT 1

I tried the @bonifacio suggestion using the following code in the Repository class of Spring JPA:

@Query("SELECT av.album.id, av.album.name, av.album.imageVersion, av.bigger, av.position FROM AlbumView av WHERE av.view.id = ?1")
List<AlbumView> findByViewId(Long id);

But I got the following response:

[
    [
        1,
        "Test Best Hits",
        1,
        true,
        1
    ]
]

The values is exactly that, but it is considering that is an array, and not an object like its supposed..

One way to do this is by changing the query to select the AlbumView entity, which contains all the desired fields from both AlbumView and Album entity, and also can use the View entity in the WHERE clause of your query.

In this case, one of the possible solutions would be using the following query:

SELECT av FROM AlbumView av WHERE av.view.id = ?1

Also, I want to note that in your first example you were trying to fetch three different objects per row, like the example bellow:

SELECT a, av.bigger, av.position FROM Album a, AlbumView av WHERE av.view.id = ? 

The reason that it does not work is because when you select more than one column (or object), you are not automatically fetching the desired fields in just one line, since Hibernate will convert the result in a Object array (Object[]) for each line of your query's result. So, unless you really need to select multiple objects in one row, it's always recommended to return only one field, or entity on each SELECT you make.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM