欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mybatis连接池,动态的Sql语句,多表查询一对多,多对多

程序员文章站 2022-05-23 17:35:48
...

1.mybatis连接池与实务

1.1mybatis连接池

可以看出 Mybatis 将它自己的数据源分为三类:

  1. UNPOOLED 不使用连接池的数据源
  2. POOLED 使用连接池的数据源
  3. JNDI 使用 JNDI 实现的数据源(基本淘汰)

MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即:
type=”POOLED”:MyBatis 会创建 PooledDataSource 实例(使用多次)
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例(只能用一次)
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="database.properties">

    </properties>
    <!--typeAliases配置别名,它只能配置domain中的别名-->
    <typeAliases>
        <!-- 单个别名定义 -->
        <typeAlias alias="hehe" type="com.xiao.domain.User"/>
        <!--批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以)-->
        <package name="com.xiao.domain"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <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>
    <mappers>
<!--        <mapper url="file:///E:/CodeSeniorJava/mybatis_04_CRUD_demo02/src/main/resources/com/xiao/dao/UserDao.xml"/>-->
    <!--package标签能够用于指定dao接口所在的包,当指定了之后就不需要再写mapper以及resource以及class了-->
        <package name="com.xiao.dao"/>
    </mappers>
</configuration>

1.2mybatis事务管理

1.2.1手动提交事务

Mybatis 中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制。

这是我们的 Connection 的整个变化过程,通过分析我们能够发现之前的 CUD 操作过程中,我们都要手动进
行事务的提交,原因是 setAutoCommit()方法,在执行时它的值被设置为 false 了,所以我们在 CUD 操作中,
必须通过 sqlSession.commit()方法来执行提交操作。

mybatis连接池,动态的Sql语句,多表查询一对多,多对多

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory factory ;
    public UserDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }
    public List<User> findAll() {
        //创建sqlSession
        SqlSession sqlSession = factory.openSession();
        //传入类型
        List<User> users = sqlSession.selectList("com.xiao.dao.UserDao.findAll");
        sqlSession.close();
        return users;
    }
     public void saveUser(User user) {
        //创建sqlSession
        SqlSession sqlSession = factory.openSession();
        //传入类型
        sqlSession.insert("com.xiao.dao.UserDao.saveUser",user);
        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }
/**
     * 创建资源
     * @throws Exception
     */
@Before
    public void Init() throws Exception{
        //加载配置文件
        is = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //创建工厂对象的工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //通过配置文件来创建工厂对象
        SqlSessionFactory factory = builder.build(is);
        //创建UserDaoImpl对象传入工厂对象,获取到实现类中的方法
        userDao = new UserDaoImpl(factory);
    }

    /**
     * 关闭资源
     * @throws Exception
     */
 @After
    public void destroy() throws Exception{
        //关闭输入流
        is.close();
    }

    /**
     * 查询所有用户信息用户
     * @throws Exception
     */
 @Test
    public void saveUserTest() throws Exception{
        User user= new User();
        user.setUsername("李四 test");
        user.setAddress("仙桃");
        user.setBirthday(new Date());
        user.setSex("男");
        System.out.println("添加之前:"+user);
        userDao.saveUser(user);
        System.out.println("添加之后:"+user);
    }

mybatis连接池,动态的Sql语句,多表查询一对多,多对多

1.2.2自动提交事务

@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(true);
//5.创建 Dao 的代理对象
userDao = session.getMapper(IUserDao.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws Exception{
//7.释放资源
session.close();
in.close();
}

所对应的 DefaultSqlSessionFactory 类的源代码:
mybatis连接池,动态的Sql语句,多表查询一对多,多对多

我们发现,此时事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就 编程而言,设置为自动提交方式为
false再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务 情况来决定提交是否进行提交。

2.mybatis动态的Sql语句

2.1动态SQL之< if >标签

持久层dao

 /**
     * 通过名字查询
     * @param user
     * @return
     */
    List<User> findByName(User user);

持久层dao的映射配置

<!--模糊查询-->
    <!--
        <if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
         另外要注意 where 1=1 的作用~!
     -->
    <!---->
    <select id="findByName" parameterType="User" resultType="User">
        <include refid="defaultSql"></include>
        <!--可以去掉where 1=1 加上 where标签-->
        <where>
            <if test="username != null and username != ''">
              and username like #{username}
            </if>
            <if test="address != null and address != ''">
                and address like #{address}
            </if>
        </where>
    </select>

测试

 @Before
    public void innit() throws Exception {
        //加载配置文件
        is = Resources.getResourceAsStream("SqlMapperConfig.xml");
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        factory = factoryBuilder.build(is);
        sqlSession = factory.openSession();
        userDao = sqlSession.getMapper(UserDao.class);
    }
@After
    public void destroy() throws IOException {
        sqlSession.close();
        is.close();
    }
@Test
    public void findByName(){
        String name = "%王%";
        User user= new User();
        user.setAddress("%仙桃%");
        user.setUsername(name);
        List<User> users = userDao.findByName(user);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }

mybatis连接池,动态的Sql语句,多表查询一对多,多对多

2.2< where >标签

为了简化上面 where 1=1 的条件拼装,我们可以采用< where >标签来简化开发
注意 sql语句后面需要加空格否则会报错
mybatis连接池,动态的Sql语句,多表查询一对多,多对多

2.3< for each >标签

传入多个 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)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。 这样我们将如何进行参数的传递?

<!-- 查询所有用户在 id 的集合之中 -->
<select id="findInIds" resultType="user" parameterType="queryvo">
<!-- select * from user where id in (1,2,3,4,5); -->
<include refid="defaultSql"></include>
	<where>
		<if test="ids != null and ids.size() > 0">
			<foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
				#{uid}
			</foreach>
		</if>
	</where>
</select>

SQL 语句:
select 字段 from user where id in (?)
标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符

2.4简化SQL片段

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
	select * from user
</sql>

<!-- 配置查询所有操作 -->
<select id="findAll" resultType="user">
	<include refid="defaultSql"></include>
</select>
<!-- 根据 id 查询 -->
<select id="findById" resultType="UsEr" parameterType="int">
	<include refid="defaultSql"></include>
	where id = #{uid}
</select>

3.mybatis多表查询一对多

4.mybatis多表查询多对多