1. 动态sql标签
①:if标签:
<if test = "username != null">
username = #{username}
</if>
②:where标签:
<where>
<!-- 添加condition -->
</where>
③:foreach标签:
<foreach collection = "ids" open = "and id in(" close = ")" separator = "," item = "id">
#{id}
</foreach>
2. 多表查询
①:一对一(多对一):
建立account表,用account账户和user联系,一个用户对应多个账户,但一个账户只可能对应一个用户,我们可以将这样的多对一的关系变成一对一来处理。
若想要查询account信息时知道这个账户的所有者user信息该如何操作?
方式一:用一个实体类AccountUser来继承User类,在toString中加入父类User的toString()方法,再将查询结果封装成AccountUser类的对象即可达到一对一关联查询出所要信息的目的。
AccountUser类:
public class AccountUser extends Account {
private String username;
private String address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return super.toString() + " AccountUser{" +
"username='" + username + '\'' +
", address='" + address + '\'' +
'}';
}
}
IAccountDao.XML文件的配置:
<select id="findAccountWithUser" resultType="cn.xupt.domain.AccountUser">
select * from account a,user u where u.id = a.uid
</select>
方式二:具有外键的表称为从表,从表中外键来源的表称为主表。可以在从表的实体类中定义主表的实体类对象,关联查询结束后将其封装为从表的实体类,主表的信息可以从从表中获得,相比于每建立一个关联查询就创建一个继承类来说这种方法肯定简单一点,但这种方法需要配置resultMap。
Account类:
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money;
}
}
IAccountDao.XMl的配置:
<resultMap id="accountMap" type="cn.xupt.domain.Account">
<!--对应列名-->
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<association property="user" column="uid" javaType="cn.xupt.domain.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</association>
</resultMap>
<select id="findAllAccount" resultMap="accountMap">
select u.*, a.id as aid, a.uid, a.money from account a,user u where u.id = a.uid
</select>
②:一对多:
一个user有多个account。
若查询一个user时想知道它的账户信息该如何操作?
方式:给User类中添加一个List<Account>集合accounts,然后创建相应的resultMap使用来获得每一个用户的账户信息。
User类:
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao.XML配置:
<resultMap id="userAccountMap" type="cn.xupt.domain.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<collection property="accounts" ofType="cn.xupt.domain.Account">
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
<select id="findAllUserWithAccount" resultMap="userAccountMap">
select * from user u left outer join account a on a.uid = u.id
</select>
③:多对多:
一个用户可以扮演多个角色,一个角色可以被多个用户扮演。
若查询角色想知道它的所有扮演者改如何操作?
分析:乍一看有点像一对多,但实则不是,里面具体的区别其实是数据库中的表之间的关系,若两个表之间有多对多的关系,我们第一个想到的是选择外键来互相约束如下图:
但是这样之后我们发现原本的对应实体类的表好像变成了对应关系的表,名字具有唯一性但是却出现了两次,针对此种现象又采用了另外一种方法:建立一个中间表来表达多对多的关系,如下图:
如此一来就解决了这个问题。
方式:定义一个新的实体类Role,Role中具有一个集合List<User> users,之后与一对多类似,只是sql语句比较不好写。
Role类:
public class Role implements Serializable {
private Integer roleId;
private String roleName;
private String roleDesc;
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"roleId=" + roleId +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
IRoleDao.XMl文件配置:
<mapper namespace="cn.xupt.dao.IRoleDao">
<resultMap id="roleUserMap" type="cn.xupt.domain.Role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="cn.xupt.domain.User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</collection>
</resultMap>
<select id="findRoleWithUser" resultMap="roleUserMap">
SELECT u.*, r.`ID` AS rid, r.`ROLE_NAME`, r.`ROLE_DESC` FROM role r
LEFT OUTER JOIN user_role ur ON r.`ID` = ur.`RID`
LEFT OUTER JOIN `user` u ON ur.`UID` = u.`ID`
</select>
</mapper>
④:心得:
(1): resultMap这个标签像是一个可以自定义的resultType标签,可以自己定义需要的resultType。
(2): 连接查询复习:
两张表:学生表和成绩表。
学生有多门成绩;
一门成绩对应一名学生。
——内连接:
内连接查询有成绩的学生信息(包括成绩信息),无成绩的学生信息不显示。
——左外连接:
左外连接查询所有学生及其成绩的信息,不管有没有成绩都要显示出来。
——右外连接:
右外连接查询所有成绩及其学生信息,不管这个成绩有没有主人(学生)都要显示出来。
——全外连接:
全外连接 = 左外连接 + 右外连接。
——自然连接:
最常见,查询一个学生的所有成绩。