一、mybatis中的连接池及事务控制
1.mybatis中的连接池使用及分析
- 1.1 连接池简介
连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
连接池就是用于存储连接的容器。该容器是一个集合对象,集合对象必须是线程安全的,不能两个线程拿到同一个连接对象。
容器必须实现队列的特性:先进先出。 - 1.2 mybatis中的连接池
<!-- 配置环境 -->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务类型 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)
type:配置连接池
取值:
POOLED:采用传统的javax.sql.DataSource规范中的连接池,在mybatis中有针对该规范的实现。
UNPOOLED:采用传统的连接方式,虽然实现了javax.sql.DataSource规范,但并没有池的思想。
JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同服务器所能拿到的DataSource是
不同的,注意,如果不是web或maven的war工程,是不能使用的。
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
2. mybatis中的事务控制使用及分析
事务是由一组操作组成的一个工作单元。
事务的四个特性:
- 原子性(ctomicity)
- 一致性(consistency)
- 隔离性(isolation)
- 持久性(durability)
二、mybatis基于XML配置的动态SQL语句的实现
- <if>标签
- <where>标签
- <foreach>标签
- <sql>代码块
<!--抽取代码块 -->
<sql id="defaultSql">
select * from
</sql>
<select id="findUserByIds" resultMap="com.seapp.domain.User" parameterType="com.seapp.domain.QueryVo">
-- 抽取代码块的引入
<include refid="defaultSql"></include>
-- where的使用
<where>
-- if的使用
<if test="ids != null and ids.size >0">
-- foreach的使用
<foreach collection="ids" open="and in (" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
三、mybatis中的多表操作
基于如下示例实现对mybatais多表操作的学习
示例:用户和账户
- 一个用户可以有多个账户
- 一个账户只能属于一个用户(多个账户也可以属于一个用户)
CREATE TABLE account (
`ID` INT (11) NOT NULL COMMENT '编号',
`UID` INT (11) DEFAULT NULL COMMENT '用户编号',
`MONEY` DOUBLE DEFAULT NULL COMMENT '金额',
PRIMARY KEY (`ID`),
KEY `FK_Reference` (`UID`),
CONSTRAINT `FK_Reference` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
操作步骤:
- 1.建立两张表:用户表、账户表,让用户表和账户表之间拥有一对多的关系。
- 2.建立两个实体类:用户实体类、账户实体类,用户实体类与账户实体类之间体现出一对多的关系。
package com.seapp.domain;
import java.util.Date;
import java.util.List;
/**
* @author seapp
* @date 2020/7/25 22:09
*/
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//在user实体类中设定与account实体类之间一对多的关系
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 + '\'' +
", accounts=" + accounts +
'}';
}
}
package com.seapp.domain;
import java.io.Serializable;
/**
* @author seapp
* @date 2020/7/28 10:10
*/
public class Account implements Serializable {
private Integer aId;
private Integer uid;
private Double money;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Integer getaId() {
return aId;
}
public void setaId(Integer aId) {
this.aId = aId;
}
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{" +
"aId=" + aId +
", uid=" + uid +
", money=" + money +
", user=" + user +
'}';
}
}
- 建立对应的配置文件。
- 实现配置:
当我们查询用户时,可以同时得到用户下所包含的账户信息。
当我们查询账户时,可以同时得到账户所属用户信息。
- 实现配置:
1. 一对一
- IAccountDao接口实现:
package com.seapp.dao;
import com.seapp.domain.Account;
import java.util.List;
/**
* @author seapp
* @date 2020/7/28 10:15
*/
public interface IAccountDao {
/**
* 查询所有账户,且关联到所属用户
* @return
*/
List<Account> findAllAccountUser();
}
- map实现
<!--实体类名与数据库列名不一致时通过resultMap来实现实体类名与列名的对应关系 -->
<resultMap id="accountUserMap" type="account">
<id column="aid" property="aId"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!--asssociation属性来确定一对一实体类,
column:由哪个字段类确定 -->
<association property="user" column="uid">
<id column="id" property="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</association>
</resultMap>
<!--查询所有,包含账户所属用户-->
<select id="findAllAccountUser" resultMap="accountUserMap">
select a.id AS aid,a.uid,a.money ,u.*
from account a ,user u
where a.uid = u.id;
</select>
2. 一对多
- IUserDao接口类实现
package com.seapp.dao;
import com.seapp.domain.QueryVo;
import com.seapp.domain.User;
import java.util.List;
/**
* @author seapp
* @date 2020/7/25 22:11
*/
public interface IUserDao {
/**
* 查询所有,且包含用户对应的账户
* @return
*/
List<User> findAll();
}
- IUserDao.xml map的实现
<resultMap id="userMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!-- 指定关联对象accounts集合的映射
ofType:指定集合中元素的类型 -->
<collection property="accounts" ofType="account">
<id property="aId" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="userMap">
SELECT
u.*, a.id AS aid,
a.uid,
a.money
FROM
USER u
LEFT OUTER JOIN account a ON a.uid = u.id;
</select>
3. 多对多
- 1.建立两张表:用户表、角色表,让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
- 2.建立两个实体类:用户实体类、角色实体类,用户实体类与账户实体类之间体现出多对多的关系。各自包含对方一个集合引用
- 建立对应的配置文件。
- 实现配置:
当我们查询用户时,可以同时得到用户包含的角色信息。
当我们查询账户时,可以同时得到所赋予的用户信息。
- 实现配置:
//角色表
CREATE TABLE role (
`ID` INT (11) NOT NULL COMMENT '编号',
`ROLE_NAME` VARCHAR (30) DEFAULT NULL COMMENT '角色名称',
`ROLE_DESC` VARCHAR (30) DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (`ID`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
//用户、角色中间表
CREATE TABLE `user_role` (
`UID` INT (11) NOT NULL COMMENT '用户编号',
`RID` INT (11) NOT NULL COMMENT '角色编号',
PRIMARY KEY (`UID`, `RID`),
KEY `FK_Reference_role` (`RID`),
CONSTRAINT `FK_Reference_role` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
CONSTRAINT `FK_Reference_user` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8;
- Role实体类实现:
package com.seapp.domain;
import java.io.Serializable;
import java.util.List;
/**
* @author seapp
* @date 2020/7/28 11:24
*/
public class Role implements Serializable {
private Integer id;
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 getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
", users=" + users +
'}';
}
}
- IRoleDao.xml实现
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.seapp.dao.IRoleDao">
<resultMap id="roleMap" type="role">
<id property="id" column="id"/>
<result property="roleName" column="role_name"/>
<result property="roleDesc" column="role_desc"/>
<collection property="users" ofType="user" >
<id column="userId" property="id" />
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAllRole" resultMap="roleMap">
SELECT
r.*, u.id AS userId,
u.username,
u.birthday,
u.sex,
u.address
FROM
role r
LEFT OUTER JOIN user_role ru ON r.id = ru.rid
LEFT OUTER JOIN USER u ON ru.uid = u.id;
</select>
</mapper>
- IUserDao.xml实现
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.seapp.dao.IUserDao">
<resultMap id="userRoleMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!--指定关联的角色集合信息-->
<collection property="roles" ofType="role">
<id property="id" column="roleId"/>
<result property="roleName" column="role_name"/>
<result property="roleDesc" column="role_desc"/>
</collection>
</resultMap>
<select id="findAllUserRole" resultMap="userRoleMap">
SELECT
u.*,r.ID AS roleId,r.ROLE_DESC,r.ROLE_NAME
FROM
USER u
LEFT OUTER JOIN user_role ru ON u.id = ru.rid
LEFT OUTER JOIN role r ON ru.uid = r.id;
</select>
</mapper>
SQL语句与返回结果的封装。
网友评论