本文共 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*/ListfindByUser(User user); 2 持久层 Dao 映射配置注意 : <if> 标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。另外要注意 where 1=1 的作用 ~ !3 测试@Testpublic void testFindByUser() {User u = new User();u.setUsername("%王%");u.setAddress("%顺义%");//6.执行操作Listusers = 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 Listids;public List getIds() {return ids;}public void setIds(List ids) {this.ids = ids;}} 2 持久层 Dao 接口/*** 根据 id 集合查询用户* @param vo* @return*/ListfindInIds(QueryVo vo); 3 持久层 Dao 映射配置SQL 语句:select 字段 from user where id in (?)<foreach> 标签用于遍历集合,它的属性:collection: 代表要遍历的集合元素,注意编写时不要写 #{}open: 代表语句的开始部分close: 代表结束部分item: 代表遍历集合的每个元素,生成的变量名sperator: 代表分隔符4 编写测试方法@Testpublic void testFindInIds() {QueryVo vo = new QueryVo();Listids = 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.id3 定义 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*/ListfindAll();} 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.执行操作Listaccountusers = 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*/ListfindAll();} 注意:第二种方式,将返回值改 为了 Account 类型。因为 Account 类中包含了一个 User 类的对象,它可以封装账户所对应的用户信息。3 重新定义 AccountDao.xml 文件 4 在 AccountTest 类中加入测试方法@Testpublic void testFindAll() {Listaccounts = 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.uid2 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 Listaccounts;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*/ListfindAll(); 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.执行操作Listusers = 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 Listusers;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*/ListfindAll();} 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(){Listroles = 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!