简体   繁体   中英

spring boot, JpaRepository Custom query inner join and view on thymeleaf, joined column is not showing

table - > UserProfile(user_id,username,status_id)

table - > Status (status_id, name)

the status_id is foreign key between tables

this is the JpaRepository

@Repository
public interface RepoUserProfile extends JpaRepository<UserProfile, Long> {  
    @Query("SELECT u,s.name FROM UserProfile u INNER JOIN Status s on s.status_id=u.status_id")
    public List<UserProfile> listUserProfile();

}

here it's been added to the service

@Service
public class ServiceUserProfile {
    @Autowired
    private RepoUserProfile repo;

    public List<UserProfile> listUserProfile() {
        return repo.listUserProfile();
    }
}

this is the controller

@Controller
public class UserController {

    @Autowired
    private ServiceUserProfile servicerepo;

    @RequestMapping("/user/list")
    public String Index(Model model) {
        List<UserProfile> listUserProfile = servicerepo.listUserProfile();
        model.addAttribute("listUser", listUserProfile);
        return "user/index";
    }
} 

here i want view in the index.html

<tbody>
    <tr th:each="litOfUser: ${listUser}">
        <td th:text="${litOfUser.username}"></td>
        <td th:text="${litOfUser.name}"></td>  // the name is not showing
    </tr>
</tbody>

why the listofUser.name is not showing when i remove this the system is working fine but not if i keep it.

means i can not view the {name} which is join from the table STATUS by the foreign key of {status_id}

thanks

When using technologies like jpa, it is best to think of entities instead of traditional tables found in the database. In your entity UserProfile, you should have the entity Status with the appropriate jpa relationship mapping. It will look something like below assuming one UserProfile can have only one Status and one Status can below to one UserProfile .

@OneToOne
@JoinColumn(name="status_id")
Status status;

In your repository, you're returning a list of UserProfile and jpa is ignoring name from status . You must create a DTO and add data from UserProfile and Status to it.

Sample DTO:

package com.example.projectx;

@Getter // from lombok
public class UserDto{
    private String name;
    private UserProfile userProfile;

    public UserDto(UserProfile userProfile, String name){
        this.userProfile = userProfile;
        this.name = name;
    }
}

Now in your repository, your query will look like:

@Repository
public interface RepoUserProfile extends JpaRepository<UserProfile, Long> {  
    @Query("SELECT new com.example.projectx.UserDto(u,s.name) FROM UserProfile u INNER JOIN u.status s")
    public List<UserDto> getUserDtos();
}

In the select statement above, I am invoking the constructor for the DTO which takes UserProfile and a String . The fully qualified name of the DTO class is required.

Refactor the service as needed;

@Service
public class ServiceUserProfile {
    @Autowired
    private RepoUserProfile repo;

    public List<UserDto> getUserDtos() {
        return repo.getUserDtos();
    }
}

Refactor controller;

@Controller
public class UserController {

    @Autowired
    private ServiceUserProfile servicerepo;

    @RequestMapping("/user/list")
    public String Index(Model model) {
        List<UserDto> userDtos = servicerepo.getUserDtos();
        model.addAttribute("userDtos ", userDtos );
        return "user/index";
    }
} 

In the thymeleaf template, it will be something like:

<tr th:each="userDto : ${userDtos }">
    <td th:text="${userDto.userProfile.username}"></td>
    <td th:text="${userDto.name}"></td>
</tr> 

Please accept the answer if it has helped you resolved your issue and have a better understanding of the technologies involved.

Happy coding!

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