Reputation: 1813
I'm using Spring and MyBatis, I'm facing with the problem when join four tables to get data in JSP my model:
User:
public class User {
private Long user_id;
private GroupMaster group_id;
private String login_name;
private String password;
private String full_name;
private String full_name_kana;
private String email;
private String tel;
private Date birthday;
private boolean rule;
private String salt;
// getter and setter
}
DetailUser:
public class DetailUserVN {
private Long detail_user_vn_id;
private User user_id;
private String code_level;
private Date start_date;
private Date end_start;
private int total;
// getter and setter
}
GroupMaster:
public class GroupMaster {
private Long group_id;
private String group_name;
// getter and setter
}
VNMaster:
class VNMaster {
private String code_level;
private String name_level;
// getter and setter
}
UserMapper.java
@Select("SELECT users.user_id, "
+ "users.full_name, "
+ "users.birthday, "
+ "mst_group.group_name, "
+ "users.email, users.tel, "
+ "mst_vn.name_level, "
+ "tbl_detail_user_vn.end_date, "
+ "tbl_detail_user_vn.total "
+ "FROM users "
+ "INNER JOIN tbl_detail_user_vn "
+ "ON tbl_detail_user_vn.detail_user_vn_id = users.user_id "
+ "INNER JOIN mst_vn "
+ "ON mst_vn.code_level = tbl_detail_user_vn.code_level "
+ "INNER JOIN mst_group "
+ "ON mst_group.group_id = users.group_id")
public List<User> getAllUsers();
UserServiceImpl:
public List<User> getAllUsers() {
return userMapper.getAllUsers();
}
UserController:
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value="/login", method=RequestMethod.POST)
public String getAllUser(ModelMap model) {
List<User> listUser = userService.getAllUsers();
model.put("listUser", listUser);
logger.info("list of renter is: " + listUser);
return "getUser";
}
}
getUser.jsp:
<div class="">
<c:if test="${not empty listUser}">
<table border="1" cellpadding="5">
<tr>
<th style="background-color: #e9ecef;">ID</th>
<th style="background-color: #e9ecef;">Họ tên ▲▽</th>
<th style="background-color: #e9ecef;">Ngày sinh</th>
<th style="background-color: #e9ecef;">Phòng ban</th>
<th style="background-color: #e9ecef;">Email</th>
<th style="background-color: #e9ecef;">Phone number</th>
<th style="background-color: #e9ecef;">Tring do ▲▽</th>
<th style="background-color: #e9ecef;">Ngay het han ▲▽</th>
<th style="background-color: #e9ecef;">Tong</th>
</tr>
<c:forEach items="${listUser}" var="user">
<tr>
<td>${user.user_id}</td>
<td>${user.full_name}</td>
<td>${user.birthday}</td>
<td>${user.group_id.group_name}</td>
<td>${user.email}</td>
<td>${user.tel}</td>
<td>${mst_vn.name_level}</td>
<td>${tbl_detail_user_vn.end_date}</td>
<td>${tbl_detail_user_vn.total}</td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
When I build it seem is not happen error but some value can not get from database
example:
<td>${user.group_id.group_name}</td>
<td>${mst_vn.name_level}</td>
<td>${tbl_detail_user_vn.end_date}</td>
<td>${tbl_detail_user_vn.total}</td>
How to fix this error and get data for this?
Updated:
org.apache.ibatis.reflection.ReflectionException: There is no setter for property named 'user' in 'class com.you.springmybatis.model.User'
Upvotes: 1
Views: 3087
Reputation: 15861
The SQL query returns the result set with data that is required but you have not specified how to map this result set to the object structure you use.
Let's consider one field value you try to display user.group_id.group_name
(for other fields the situation is more complex, see below some thoughts about this).
The data for group name is returned in the field that has name group_name
in the result set. But mybatis does not know that for this field and object of type GroupMaster
should be created and that the value from group_name
should be set to the group_name
property of that object.
You need to specify the mapping for the association between User
and GroupMaster
entities. Unfortunately when you select the entity and associated entity via single query using a join it is not possible to map such association using annotations in mybatis. But this can be done using xml mapping.
But before you start you need to include unique id of every entity that participates in the join to the result set. That means you need to include group_id
etc. Without these fields mybatis will create duplicate entities but you most probably want to have only one GroupMaster
created for different User
entities if they refer to the same record in mst_group
table.
You create xml mapping in UserMapper.xml
that resides in the same package as UserMapper
interface similar to this:
<resultMap id="userMap" type="User">
<id property="user_id" column="user_id"/>
<result property="full_name" column="full_name"/>
<result property="birthday" column="birthday"/>
<association property="group_id" javaType="GroupMaster">
<id property="group_id" column="group_id"/>
<result property="group_name" column="group_name"/>
</association>
</resultMap>
Then you can reference this resultmap in the mapper:
@ResultMap("com.you.mapper.UserMapper.userMap")
@Select("SELECT users.user_id, "
+ "users.full_name, "
+ "users.birthday, "
+ "mst_group.group_name, "
+ "users.email, users.tel, "
+ "mst_vn.name_level, "
+ "tbl_detail_user_vn.end_date, "
+ "tbl_detail_user_vn.total "
+ "FROM users "
+ "INNER JOIN tbl_detail_user_vn "
+ "ON tbl_detail_user_vn.detail_user_vn_id = users.user_id "
+ "INNER JOIN mst_vn "
+ "ON mst_vn.code_level = tbl_detail_user_vn.code_level "
+ "INNER JOIN mst_group "
+ "ON mst_group.group_id = users.group_id")
public List<User> getAllUsers();
Let's see in details how association mapping works:
<resultMap id="RM" type="A">
<association property="pB" javaType="B">
<id property="id" column="b_id"/>
<result property="name" column="b_name"/>
</association>
</resultMap>
This specifies that for every result row (that represents object of type A
) an object of type B
should be created and its properties id
and name
should be set from columns b_id
and b_name
respectively.
So the above mapping for you example specifies that fields group_id
and group_name
should be put into the properties of the object of type GroupMaster
and that object should be assigned to the group_id
property of the User
entity.
Several notes:
group_id
field in User
actually stores not the id of the group, but the actual object so it should be renamed to group
.full_name
the property should be fullName
etc.There is a problem with mapping of joins to mst_vn
and tbl_detail_user_vn
as there are no field representing this associations in the User
. You need to think about how you want you object tree should look like to represent the data you want to fetch from the database.
For tbl_detail_user_vn
you probably need to add a field to User
:
private DetailUserVN detail;
Then you will be able to map this association using the same method as for GroupMaster
.
Upvotes: 1