MyBatis(三)
发布日期:2021-07-22 10:54:12 浏览次数:9 分类:技术文章

本文共 12449 字,大约阅读时间需要 41 分钟。

目录


mybatis中的连接池以及事务控制    

1、连接池

  (可以减少我们获取连接所消耗的时间)

    连接池就是用于存储连接的一个容器;

    容器其实就是一个集合对象,该集合必须是线程安全的,不能两个线程拿到同一连接;该集合还必须实现队列的特性:先进先出

2、mybatis中的连接池
    mybatis连接池提供了3种方式的配置:
        配置的位置:
            主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
        type属性的取值:
            POOLED     采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现

    配置连接的原理:

            UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想
            JNDI     采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样
                 注意:如果不是web或者maven的war工程,是不能使用的。
                 tomcat服务器,采用连接池就是dbcp连接池。
3、mybatis中的事务
    事务的四大特性ACID
    不考虑隔离性会产生的3个问题
    解决办法:四种隔离级别

    它是通过sqlsession对象的commit方法和rollback方法实现事务的提交和回滚

mybatis基于XML配置的动态SQL语句使用   

    mappers配置文件中的几个标签:

        <if>

1
持久层
Dao
接口
/*** 根据用户信息,查询用户列表* @param user* @return*/List
findByUser(User user);
2
持久层
Dao
映射配置
注意
<if>
标签的
test
属性中写的是对象的属性名,如果是包装类的对象要使用
OGNL
表达式的写法。
另外要注意
where 1=1
的作用
~
3
测试
@Testpublic void testFindByUser() {User u = new User();u.setUsername("%王%");u.setAddress("%顺义%");//6.执行操作List
users = userDao.findByUser(u);for(User user : users) {System.out.println(user);}}

        <where>

为了简化 
where 1=1
的条件拼装,我们可以采用
<where>
标签来简化开发。
1
持久层
Dao
映射配置
<!--
根据用户信息查询
-->

        <foreach>

传入多个
id
查询用户信息,用下边两个
sql
实现:
SELECT * FROM USERS WHERE username LIKE '%
%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%
%' AND id IN (10,89,16)
我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。
 
1
QueryVo
中加入一个
List
集合用于封装参数
/**** 

Title: QueryVo

*

Description: 查询的条件

*

Company: http://www.itheima.com/

*/public class QueryVo implements Serializable {private List
ids;public List
getIds() {return ids;}public void setIds(List
ids) {this.ids = ids;}}
2
持久层
Dao
接口
/*** 根据 id 集合查询用户* @param vo* @return*/List
findInIds(QueryVo vo);
3
持久层
Dao
映射配置
SQL
语句:
select
字段
from user where id in (?)
<foreach>
标签用于遍历集合,它的属性:
collection:
代表要遍历的集合元素,注意编写时不要写
#{}
open:
代表语句的开始部分
close:
代表结束部分
item:
代表遍历集合的每个元素,生成的变量名
sperator:
代表分隔符
编写测试方法
@Testpublic void testFindInIds() {QueryVo vo = new QueryVo();List
ids = new ArrayList
();ids.add(41);ids.add(42);ids.add(43);ids.add(46);ids.add(57);vo.setIds(ids);//6.执行操作List
users = userDao.findInIds(vo);for(User user : users) {System.out.println(user);}}

        <sql>

Sql
中可将重复的
sql
提取出来,使用时用
include
引用即可,最终达到
sql
重用的目的。
1
定义代码片段
select * from user
2
引用代码片段

mybatis中的多表操作     

mybatis中的多表查询

    表之间的关系有几种
        一对多
        多对一
        一对一
        多对多 

 多表查询之多对一(一对一)

    mybatis中的多表查询:

        示例:用户和账户
            一个用户可以有多个账户
            一个账户只能属于一个用户(多个账户也可以属于同一个用户)
        步骤:
            1、建立两张表:用户表,账户表
                让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
            2、建立两个实体类:用户实体类和账户实体类
                让用户和账户的实体类能体现出来一对多的关系
            3、建立两个配置文件
                用户的配置文件
                账户的配置文件
            4、实现配置:
                当我们查询用户时,可以同时得到用户下所包含的账户信息
                当我们查询账户时,可以同时得到账户的所属用户信息

方法一:

1
定义账户信息的实体类
/**** 

Title: Account

*

Description: 账户的实体类

*

Company: http://www.itheima.com/

*/public class Account implements Serializable {private Integer id;private Integer uid;private Double money;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;}@Overridepublic String toString() {return "Account [id=" + id + ", uid=" + uid + ", money=" + money + "]";}}
2
编写
Sql
语句
实现查询账户信息时,也要查询账户所对应的用户信息。
SELECTaccount.*,user.username,user.addressFROMaccount,userWHERE account.uid = user.id
3
定义
AccountUser
为了能够封装上面
SQL
语句的查询结果,定义
AccountCustomer
类中要包含账户信息同时还要包含用户信 息,所以我们要在定义 AccountUser
类时可以继承
User
/**** 

Title: AccountUser

*

Description: 它是 account 的子类

*

Company: http://www.itheima.com/

*/public class AccountUser extends Account implements Serializable {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;}@Overridepublic String toString() {return super.toString() + " AccountUser [username=" + username + ",address=" + address + "]";}}
4
定义账户的持久层
Dao
接口
/**** 

Title: IAccountDao

*

Description: 账户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IAccountDao {/*** 查询所有账户,同时获取账户的所属用户名称以及它的地址信息* @return*/List
findAll();}
5
定义
AccountDao.xml
文件中的查询配置信息
注意
:因为上面查询的结果中包含了账户信息同时还包含了用户信息,所以我们的返回值类型 returnType 的值设置为 AccountUser
类型,这样就可以接收账户信息和用户信息了
6
创建
AccountTest
测试类
/**** 

Title: MybastisCRUDTest

*

Description: 一对多账户的操作

*

Company: http://www.itheima.com/

*/public class AccountTest {private InputStream in ;private SqlSessionFactory factory;private SqlSession session;private IAccountDao accountDao;@Testpublic void testFindAll() {//6.执行操作List
accountusers = accountDao.findAll();for(AccountUser au : accountusers) {System.out.println(au);}}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 SqlSession 对象session = factory.openSession();//5.创建 Dao 的代理对象accountDao = session.getMapper(IAccountDao.class);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{session.commit();//7.释放资源session.close();in.close();}}

 方式二

使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果

通过面向对象的
(has a)
关系可以得知,我们可以在
Account
类中加入一个
User
类的对象来代表这个账户 是哪个用户的
1
修改
Account
Account
类中加入
User
类的对象作为
Account
类的一个属性。
/**** 

Title: Account

*

Description: 账户的实体类

*

Company: http://www.itheima.com/

*/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;}@Overridepublic String toString() {return "Account [id=" + id + ", uid=" + uid + ", money=" + money + "]";}}
2
修改
AccountDao
接口中的方法
/**** 

Title: IAccountDao

*

Description: 账户的持久层接口

*

Company: http://www.itheima.com/

*/public interface IAccountDao {/*** 查询所有账户,同时获取账户的所属用户名称以及它的地址信息* @return*/List
findAll();}
注意:第二种方式,将返回值改 为了
Account
类型。
因为
Account
类中包含了一个
User
类的对象,它可以封装账户所对应的用户信息。
3
重新定义
AccountDao.xml
文件
4
AccountTest
类中加入测试方法
@Testpublic void testFindAll() {List
accounts = accountDao.findAll();for(Account au : accounts) {System.out.println(au);System.out.println(au.getUser());}}

 

 多表查询之一对多

1
编写
SQL
语句
SELECTu.*, acc.id id,acc.uid,acc.moneyFROMuser uLEFT JOIN account acc ON u.id = acc.uid
2 User
类加入
List<Account>
/**** 

*

Description: 用户的实体类

*

Company: http://www.itheima.com/

*/public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;private List
accounts;public List
getAccounts() {return accounts;}public void setAccounts(List
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;}@Overridepublic String toString() {return "User [id=" + id + ", username=" + username + ", birthday=" + birthday+ ", sex=" + sex + ", address="+ address + "]";}}
3
用户持久层
Dao
接口中加入查询方法
/*** 查询所有用户,同时获取出每个用户下的所有账户信息* @return*/List
findAll();
4
用户持久层
Dao
映射文件配置
collection
部分定义了用户关联的账户信息。表示关联查询结果集
property
=
"accList"
关联查询的结果集存储在
User
对象的上哪个属性。
ofType
=
"account"
指定关联查询的结果集中的对象类型即
List
中的对象类型。此处可以使用别名,也可以使用全限定名。
5
测试方法
/**** 

Title: MybastisCRUDTest

*

Description: 一对多的操作

*

Company: http://www.itheima.com/

*/public class UserTest {private InputStream in ;private SqlSessionFactory factory;private SqlSession session;private IUserDao userDao;@Testpublic void testFindAll() {//6.执行操作List
users = userDao.findAll();for(User user : users) {System.out.println("-------每个用户的内容---------");System.out.println(user);System.out.println(user.getAccounts());}}@Before//在测试方法执行之前执行public void init()throws Exception {//1.读取配置文件in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.创建 SqlSession 工厂对象factory = builder.build(in);//4.创建 SqlSession 对象session = factory.openSession();//5.创建 Dao 的代理对象userDao = session.getMapper(IUserDao.class);}@After//在测试方法执行完成之后执行public void destroy() throws Exception{session.commit();//7.释放资源session.close();in.close();}}

 多表查询之多对多

        示例:用户和角色

            一个用户可以有多个角色
            一个角色可以赋予多个用户
        步骤:
            1、建立两张表:用户表,角色表
                让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键
            2、建立两个实体类:用户实体类和角色实体类
                让用户和角色的实体类能体现出来多对多的关系
                各自包含对方一个集合引用
            3、建立两个配置文件
                用户的配置文件
                角色的配置文件
            4、实现配置:
                当我们查询用户时,可以同时得到用户所包含的角色信息
                当我们查询角色时,可以同时得到角色的所赋予的用户信息

实现 Role User 多对多
 1
用户与角色的关系模型

2
业务要求及实现
SQL
需求:
实现查询所有对象并且加载它所分配的用户信息。
分析:
查询角色我们需要用到
Role
表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中 间表(USER_ROLE
)
才能关联到用户信息
语句
SELECTr.*,u.id uid,u.username username,u.birthday birthday,u.sex sex,u.address addressFROMROLE rINNER JOINUSER_ROLE urON ( r.id = ur.rid)INNER JOINUSER uON (ur.uid = u.id);
3
编写角色实体类
/*** @author 黑马程序员* @Company http://www.ithiema.com*/public class Role implements Serializable {private Integer roleId;private String roleName;private String roleDesc;//多对多的关系映射:一个角色可以赋予多个用户private List
users;public List
getUsers() {return users;}public void setUsers(List
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;}@Overridepublic String toString() {return "Role{" +"roleId=" + roleId +", roleName='" + roleName + '\'' +", roleDesc='" + roleDesc + '\'' +'}';}}
4
编写
Role
持久层接口
/*** @author 黑马程序员* @Company http://www.ithiema.com*/public interface IRoleDao {/*** 查询所有角色* @return*/List
findAll();}
5
编写映射文件
6
编写测试类
/*** @author 黑马程序员* @Company http://www.ithiema.com*/public class RoleTest {private InputStream in;private SqlSession sqlSession;private IRoleDao roleDao;@Before//用于在测试方法执行之前执行public void init()throws Exception{//1.读取配置文件,生成字节输入流in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.获取 SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//3.获取 SqlSession 对象sqlSession = factory.openSession(true);//4.获取 dao 的代理对象roleDao = sqlSession.getMapper(IRoleDao.class);}@After//用于在测试方法执行之后执行public void destroy()throws Exception{//提交事务// sqlSession.commit();//6.释放资源sqlSession.close();in.close();}/*** 测试查询所有*/@Testpublic void testFindAll(){List
roles = roleDao.findAll();for(Role role : roles){System.out.println("---每个角色的信息----");System.out.println(role);System.out.println(role.getUsers());}}}

 

转载地址:https://blog.csdn.net/m0_56426304/article/details/117880603 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:MyBatis(四)
下一篇:MyBatis(二)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月22日 20时55分24秒