Mybatis学习第三天:Mybatis 连接池 多表操作

文章目录

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连接池。)

autocommit 自动提交

可以在生产session时调用SqlSession openSession(boolean var1) 方法来实现自动提交

即将session=sqlSessionFactory.openSession(); 改为session=sqlSessionFactory.openSession(true);

这时完成后就无需进行手动提交了

事务

https://www.cnblogs.com/dongguangming/p/12846052.html

resultmap

https://blog.csdn.net/weixin_44306005/article/details/88100858

mybatis标签

if和where

如果我们想实现根据已有的条件来查询用户的功能,就可以使用if和where标签

例:List finddataUser(User user);

    <select id="finddataUser" resultType="com.gegege.domain.User" parameterType="com.gegege.domain.User">
        select * from user
        <where>
            <if test="username != null ">
               and username = #{username}
            </if>
            <if test="sex != null">
                and sex = #{sex}
            </if>
        </where>
    </select>

foreach

有时我们会想要实现下面这样的语句

select * from user where id in (41,42,43,44,45,46);

我们可以定义一个实体类叫queryvo里面存放list< integer>类型的list

dao接口中添加

List<User> getListFindUser(User user);

更改IUserDao.xml

    <resultMap id="usermap" type="com.gegege.domain.User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>

    </resultMap>
<select id="getListFindUser" resultMap="usermap" parameterType="com.gegege.domain.QuertyVo">
        select * from user
        <where>
            <if test="idList != null and idList.size() != null">
                <foreach collection="idList" item="id" open="and id in ( " close=")" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

编写test函数:

   /**
     * 测试foreach
     */
    @Test
    public void testforeach() {
        List<Integer> list=new ArrayList<Integer>();
        QuertyVo vo = new QuertyVo();
        list.add(41);
        list.add(42);
        list.add(43);
        list.add(44);
        list.add(45);
        list.add(46);
        vo.setIdList(list);
         List<User> list2=dao.getListFindUser(vo);
        list2.forEach(System.out::println);
    }
}

SQL标签

对于重复的SQL语句我们可以采用

<sql id="select*"> select * from user</sql>

此标签来进行定义

在需要调用时使用

<include refid="select*"></include>

此语句进行调用

多表查询

先了解一下表之间的关系

Mybatis学习第三天:Mybatis 连接池 多表操作

先了解一下测试用的数据库

数据库分为用户数据库User:

Mybatis学习第三天:Mybatis 连接池 多表操作

账户数据库account:

Mybatis学习第三天:Mybatis 连接池 多表操作

其中account.uid的外键设置为User.id

那么我们先做好准备工作:

1.创建javabean

2.创建IAccountDao接口

一对一操作

如果我们在查找Account时,也需要一并找到对应用户的姓名地址

这时我们可以写出下面这样的sql语句

SELECT a.* , u.username,u.address FROM account a, user u where u.id = a.uid

便可以查询到需要的数据

但这时没有用来存储返回数据的对象

所以我们要创建一个新的javabean

Mybatis学习第三天:Mybatis 连接池 多表操作

此时便可以配置xml来进行接口的实现

    <select id="FindAllAccountUser" resultType="com.gegege.domain.AccountUser">
        SELECT a.* , u.username,u.address FROM account a, user u where u.id = a.uid
    </select>

这时就可以尝试调用

    private InputStream in;
    private SqlSession session;
    private IAccountDao dao;
    @Before
    public void before() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        session= builder.build(in).openSession(true);
        dao=session.getMapper(IAccountDao.class);
    }
    @After
    public void after() throws IOException {
        in.close();
        session.close();
    }
    /**
     * 查找所有账户及对应用户的姓名地址
     */
    @Test
    public void FindAllAccountUser() {
        List<AccountUser> list=dao.FindAllAccountUser();
        list.forEach(System.out::println);
    }

此时便可以获得结果:

Mybatis学习第三天:Mybatis 连接池 多表操作

一对多操作

由上面两表可知 一个用户可以拥有多个账户,这便是一对多的关系

我们怎么实现一对多的查询呢

同样我们先写出sql语句

SELECT u.*,a.ID as aid,a.UID , a.MONEY FROM user u LEFT JOIN account a on u.id = a.UID

同样我们也需要存储的容器,

在user的javabean中添加一个list即可

private List<Account> list;

更改xml文件

    <resultMap id="selectUserAccount" type="com.gegege.domain.User">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <collection property="list" ofType="com.gegege.domain.Account">
            <id column="aid" property="id"></id>
            <result column="uid" property="uid"></result>
            <result column="money" property="money"></result>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="selectUserAccount">
        SELECT u.*,a.ID as aid,a.UID , a.MONEY FROM user u LEFT JOIN account a on u.id = a.UID
    </select>

测试一下

 private InputStream in;
    private SqlSessionFactoryBuilder sessionFactoryBuilder;
    private SqlSessionFactory sqlSessionFactory;
    private SqlSession session;
    private IUserDao dao;
    @Before
    public void before() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建工具
        sessionFactoryBuilder=new SqlSessionFactoryBuilder();
        //创建工厂
        sqlSessionFactory=sessionFactoryBuilder.build(in);
        //生产session
        session=sqlSessionFactory.openSession();
        //使用sqlsession 创建代理对象
        dao=session.getMapper(IUserDao.class);
    }
    @After
    public void after() throws IOException {
        //提交操作
        session.commit();
        //释放资源
        session.close();
        in.close();
    }
    /**
     * 测试查找
     * @throws IOException
     */
    @Test
    public void testFindAll() {
        //调用findall
        List<User> users=dao.findAll();
        for (User user:users
        ) {
            System.out.println(user+""+user.getList());
        }
    }

输出结果为:

Mybatis学习第三天:Mybatis 连接池 多表操作

多对多操作

Mybatis学习第三天:Mybatis 连接池 多表操作

按照步骤来建立数据库

建立完成后有这样三个表

1.角色表(role):

Mybatis学习第三天:Mybatis 连接池 多表操作

2.用户表(user):

Mybatis学习第三天:Mybatis 连接池 多表操作

3.中间表(user_role):

UID的外键是user表中的id

RID的外键是角色表中的ID

Mybatis学习第三天:Mybatis 连接池 多表操作

和一对多操作相同,我们想要查询用户表时可以查询到对应角色相关信息

查询角色表时可以查询到对应用户相关信息

可以写出sql语句:

        SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r
        right JOIN user_role ur ON rid = r.id
        right JOIN user u ON uid = u.id
        SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r
        LEFT JOIN user_role ur ON rid = r.id
        LEFT JOIN user u ON uid = u.id

有了sql语句则需要存储查询结果

则在user的javabean中和role的javabean中添加彼此的list用来存储

之后声明resultMap

    <resultMap id="Rolemap" type="com.gegege.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="com.gegege.domain.User">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </collection>
    </resultMap>
    <resultMap id="usermap" type="com.gegege.domain.User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="address" property="address"/>
        <collection property="roles" ofType="com.gegege.domain.Role">
            <id property="roleid" column="rid"></id>
            <result property="rolename" column="ROLE_NAME"></result>
            <result property="roledesc" column="ROLE_DESC"></result>
        </collection>
    </resultMap>

声明sql查询

    <select id="findAll" resultMap="Rolemap" >
        SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r
        LEFT JOIN user_role ur ON rid = r.id
        LEFT JOIN user u ON uid = u.id
    </select>
    <select id="findAll"  resultMap="usermap" >
        SELECT r.ID AS rid,r.ROLE_NAME,ROLE_DESC,u.* FROM role r
        right JOIN user_role ur ON rid = r.id
        right JOIN user u ON uid = u.id
    </select>

扩展:JNDI

jndi类似于windows中的注册表,存储了键值对

需要注意项目需要时war工程 且经过tomcat服务器才可以运行

首先,将之前mybatis的工程复制过来

配置javaweb环境:

添加下面两个jar包即可

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
    </dependency>

配置JNDI环境:

– 1.在webapp文件夹下创建META-INF文件夹

– 2.在文件夹下创建context.xml文件

– 3.将以下配置内容添加到context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- 
<Resource 
name="jdbc/eesy_mybatis"                        数据源的名称
type="javax.sql.DataSource"                     数据源类型
auth="Container"                                数据源提供者
maxActive="20"                                  最大活动数
maxWait="10000"                                 最大等待时间
maxIdle="5"                                     最大空闲数
username="root"                                 用户名
password="1234"                                 密码
driverClassName="com.mysql.jdbc.Driver"         驱动类
url="jdbc:mysql://localhost:3306/eesy_mybatis"  连接url字符串
/>
 -->
<Resource 
name="jdbc/mybatis"
type="javax.sql.DataSource"
auth="Container"
maxActive="20"
maxWait="10000"
maxIdle="5"
username="root"
password="adminadmin"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mybatis"
/>
</Context>

– 4.更改SqlMapConfig.xml

将原来存放数据库url密码等信息的位置更改为

这里要注意:“java:comp/env/”这段是固定的,而后面内容为自己定义的名称

    <dataSource type="JNDI">
                <property name="data_source" value="java:comp/env/jdbc/mybatis"/>
    </dataSource>**

此时执行test便发现会报错

因为要使用JNDI是需要经过服务器的

这时就要用到jsp来连接数据库

<%@ page import="org.apache.ibatis.io.Resources" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactoryBuilder" %>
<%@ page import="com.gegege.dao.IUserDao" %>
<%@ page import="com.gegege.domain.User" %>
<%@ page import="java.util.List" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactory" %>
<%@ page import="org.apache.ibatis.session.SqlSession" %>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %>
<html>
<body>
<%
    InputStream in;
    SqlSessionFactoryBuilder sessionFactoryBuilder;
    SqlSessionFactory sqlSessionFactory;
    SqlSession session2;
    IUserDao dao;
    in = Resources.getResourceAsStream("SqlMapConfig.xml");
    //创建工具
    sessionFactoryBuilder=new SqlSessionFactoryBuilder();
    //创建工厂
    sqlSessionFactory=sessionFactoryBuilder.build(in);
    //生产session
    session2=sqlSessionFactory.openSession();
    //使用sqlsession 创建代理对象
    dao=session2.getMapper(IUserDao.class);
    //调用findall
    List<User> users=dao.findAll();
    for (User user:users
    ) {
        System.out.println(user);
    }
    //提交操作
    session2.commit();
    //释放资源
    session2.close();
    in.close();
%>
</body>
</html>

此时运行打开index.jsp

便会发现控制台输出了数据库中的数据


上一篇:一起玩转树莓派(18)——MPU6050螺旋仪加速度传感器模块应用(二)


下一篇:Illustrator 半透明彩色字体