Back End/Spring Data JPA

[Spring JPA] How to retrieve Only SuperClass from a class hierarchy.

DevPing9_ 2022. 1. 28. 18:47

StackOverFlow 에서 아무도 해결 못했던데...!

제가 해냈습니다 여러분...!

✌️✌️✌️

 

 

I see many posts lead us to @Polymorphism(PolymorphismType.EXPLICIT) and using @Customizer from EclipseLink.

 

I could confidently tell you that those approach wouldn't work because I tested it already.

 

And I guess many people solved it with native query but if you want to know the way not using it, read my post.

 

There are 2 ways to select only superclass within @Inheritance.

 

1. Make Immutable Read-Only Entity.

2. Using Interface-Based DTO Projection.

 

 

I will skip immutable-approach and show you guys how to do it with DTO-Projection.

 

Without further ado, Let's crack this down.

 

These are my code snippets.

 


 

# Entity 

// SuperClass - Item
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="dtype")
@Getter @ToString
@NoArgsConstructor @AllArgsConstructor
@Entity
public class Item{
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    public Long itemId; //FolderId & BookmarkId
    public String name;
    public Long parentId;
    public BigDecimal visitCount;
    public Long userId;
}

// SubClass 1 - Folder
@Getter @NoArgsConstructor
@ToString(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Entity
public class Folder extends Item{
    private String test;
}

// SubClass 2 - Bookmark
@Getter @NoArgsConstructor
@ToString(callSuper = true)
@Entity
public class Bookmark extends Item {
    private String url;
    private String comment;    
}

 

# Interface-Based Projection

// Interface for Projection
public interface ItemOnlyRes{
        Long getId();
        Long getItemId();
        String getName();
        Long getParentId();
        Long getUserId();

        default
        String toText(){
            return getId()+" "+getName(); 
        }
}

// Repository for SuperClass - Item
public interface ItemRepository extends JpaRepository<Item,Long> {
    List<ItemOnlyRes> findByItemId(Long itemId);
}

 

# Test

    @Test
    void test(){
        /* making Folder and Bookmark and Saving those
             .... .... ....
             folderRepository.saveAll(Arrays.asList(rootfolder, afolder,bfolder));
             bookmarkRepository.saveAll(Arrays.asList(aMark, bMark,cMark));
        */

        // easy easy right?
        em.flush(); em.clear();
        itemRepository.findByItemId(1L);
    }

 

Then, you can see clean SELECT Query without Outer Join like This !!!  

 

 

Hope it'd be helpful :D ..!

 

 

 

 

 

[Notice]

I found Interface-Based Projection works well under version 2.6.1 but doesn't work in 2.6.3.

 

728x90