框架阶段:mybatis

1. mybatis简介

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

2. 通过入门案例了解mybatis

2.1 mybatis环境

  1. 新建maven项目,导入mybatis相关的依赖
<!--    mybaits-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
<!--    mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
<!--    log4j-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
<!--    junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
    </dependency>
  1. 数据库环境
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
  1. log4j配置文件(log4j.properties)
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
  1. mybaits主配置文件(SqlSessionFactory.xml)
<?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>
<!--    配置环境-->
    <environments default="mysql">
<!--        配置MySQL的环境-->
        <environment id="mysql">
<!--            配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
<!--            配置连接池-->
            <dataSource type="POOLED">
                <!--            配置数据库的基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource
        </environment>
    </environments>
<!--    指定映射配置文件-->
    <mappers>
        <mapper resource="com/itzpx/dao/IUserDao.xml"/>
    </mappers>
</configuration>
  1. dao(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.itzpx.dao.IUserDao">
<!--    配置查询所有-->
    <select id="findAll" resultType="com.itzpx.domain.User">
        select * from user
    </select>
</mapper>
  1. dao(mapper)IUserDao.java
public interface IUserDao {
    //查询所有
    List<User> findAll();
}
  1. 实体类domain
public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

注意

  1. log4j.properties、SqlMapConfig.xml文件放在resource目录下
  2. IUserDao.java文件必须与IUserDao.xml文件目录相同

2.2 有了以上环境就可以实现入门案例

@Test
    public void TestFindAll() throws Exception {
        //1.读取配置文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        //3.使用工厂生成SQLSession对象
        SqlSession sqlSession = factory.openSession();
        //4.使用SqlSession创建Dao接口的代理对象
        IUserDao dao = sqlSession.getMapper(IUserDao.class);
        //5.使用代理对象执行方法
        List<User> all = dao.findAll();
        for (User user : all) {
            System.out.println(user);
        }
        //6.释放资源
        sqlSession.close();
        is.close();
    }

2.3 通过入门案例简单分析里面的对象

  1. SqlSessionFactory (SqlSession工厂对象)
    功能:
    一,加载SqlMapConfig.xml配置文件,连接数据库
    二,读取SqlMapConfig.xml配置文件下配置的映射文件信息
    三,生产Session
    方法:
    一,openSession();产生session对象
  2. SqlSession (数据库操作对象)
    功能:
    一,产生动态代理对象(该对象取代实现类)
    二,执行sql查询
    方法:
    一,getMapper(Class);产生动态代理对象
    二,**commit();**提交事务
    三,里面定义了增删改查的所有方法来执行sql语句
  3. SqlSessionFactoryBuilder 创建工厂的对象
    功能:
    一,创建SqlSessionFactory 对象,SqlSessionFactory 是个接口,无法new
    方法:
    一,build(InputStream);加载配置文件,创建工厂对象

3. mybaits的crud

3.1 简单的crud

一. 添加User

<!--    添加User-->
    <insert id="saveUser" parameterType="com.itzpx.domain.User">
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address});
    </insert>

其中

  1. id=“saveUser” 表示IUserDao中定义的添加方法名字为saveUser
  2. parameterType="com.itzpx.domain.User"表示传递的参数类型为User对象
  3. selectKey标签为获取插入后的id
  4. keyProperty实体类的id
  5. keyColumn表中的id
  6. resultType返回值类型
  7. #{username}代表获取传递过来的User对象中的username属性值,如果属性值与该属性的getUsername方法的Username不同,以Username为准。

二、删除User

<!--    删除User-->
    <delete id="deletUser" parameterType="Integer">
        delete from user where id = #{id}
    </delete>

三、修改User

<!--    修改User-->
    <update id="updateUser" parameterType="com.itzpx.domain.User">
        update user set username = #{username},birthday = #{birthday},sex = #{sex},address = #{address} where id = #{id}
    </update>

四、查询

<!--    根据用户名查询-->
    <select id="findUserbyUserName" parameterType="String" resultType="com.itzpx.domain.User">
        select * from user where username = #{username}
    </select>

五、模糊查询两种方式给%%
第一种方式在调用方法的时候需要传递%参数%
也就是List users = dao.findUserByUsernameLike("%王%");

<!--    模糊查询-->
    <select id="findUserByUsernameLike" parameterType="String" resultType="com.itzpx.domain.User">
        select * from user where username like #{username}
    </select>

第二种方式使用’%${value}%'的书写格式给百分号

	<select id="findUserByUsernameLike2" parameterType="String" resultType="com.itzpx.domain.User">
        select * from user where username like '%${value}%'
    </select>

注意${value}中的value是固定的,不能修改
第一种方式sql语句参数的赋值为占位符方式,也就是%?%,用paramters去赋值
第二种方式sql语句参数为拼接字符串的方式,也就是%王%

提问,为什么可以使用属性直接获取值呢?

  1. mybaits使用了OGNL表达式,对象图导航语言,也就是省略了user.getXXX()。
    直接使用user.XXX的方式,而在parpameterType中已经提供了user,所以在取值的时候,可以直接使用XXX。
    XXX代表属性名称,getXXX().

3.2 深入复杂的crud

一、条件类型的封装
将多个对象封装为一个对象作为查询条件进行查询

public class QueryVo {
    public User getUser() {
        return user;
    }
<!--    条件类型的封装-->
    <select id="findUserByQueryVo" parameterType="com.itzpx.domain.QueryVo" resultType="com.itzpx.domain.User">
        select * from user where username like #{user.userName}
    </select>

注意:在开发过程中,可能需要将一个或多个对象,封装为一个对象进行查询,所以在取值的时候需要用点来获取对象中的属性值
二、当数据库列名与实体类中的属性名不一致,怎么办?
解决方法:

  1. 查询语句取别名
<select id="findAll" resultType="com.itzpx.domain.User">
        select id as userId,username as userName,birthday as userBirthday,sex as userSex,address as userAddress from user 
</select>
  1. resultMap方式
    <resultMap id="userMap" type="com.itzpx.domain.User">
        <id property="userId" column="id"/>
        <result property="userName" column="username"/>
        <result property="userBirthday" column="birthday"/>
        <result property="userSex" column="sex"/>
        <result property="userAddress" column="address"/>
    </resultMap>
<!--    配置查询所有-->
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>

注意:resultMap=“userMap”

4. properties标签的使用

第一种

	<properties>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///mybatis?characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </properties>
<!--    配置环境-->
    <environments default="mysql">
<!--        配置MySQL的环境-->
        <environment id="mysql">
<!--            配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
<!--            配置连接池-->
            <dataSource type="POOLED">
                <!--            配置数据库的基本信息-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

第二种、将配置信息定义到jdbcConfig.properties文件中

<properties resource="jdbcConfig.properties">
    </properties>
<!--    配置环境-->
    <environments default="mysql">
<!--        配置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>

注意:里面还有个属性是url,是统一资源定位符
写法为:协议,主机名,端口号,uri
支持http协议
也支持file协议

5. typeAliases标签的使用

主配置文件下的标签
主要功能,给domain下的实体类其别名

<typeAliases>
       <typeAlias type="com.itzpx.domain.User" alias="user"></typeAlias>
</typeAliases>

起完别名后不再区分大小写
也就是说在mapper.xml文件中就就不用写全限定类名了,直接写别名
当然,一个一个的起别名,很麻烦,不如一起起别名

<typeAliases>
<!--        <typeAlias type="com.itzpx.domain.User" alias="user"></typeAlias>-->
        <package name="com.itzpx.domain"/>
    </typeAliases>

这种方式以domain包下面的实体类,类名为别名
package标签还有一种使用

<!--    指定映射配置文件-->
    <mappers>
<!--        <mapper resource="com/itzpx/dao/IUserDao.xml"/>-->
<!--        <mapper class="com.itzpx.dao.IUserDao"/>-->
        <package name="com.itzpx.dao"/>
    </mappers>

在指定加载映射配置文件的时候,一个一个加太麻烦,一股脑的加
注意:不管是mapper.xml方式,还是注解方式都不用写了,也就是不用写resource,和class

6. 连接池

6.1 连接池的使用

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

6.2 连接池分析

UNPOOLED
在mybatis中的实现类是UnpooledDataSource
其通过分析getConnection()方法可以看出
其获取Connection的方式是直接加载驱动,获取连接后返回连接
由此可以看出其并未使用连接池
POOLED
在mybatis中的实现类是PooledDataSource
getConnection()方法调用了popConnection()
步骤

  1. while(conn == null) {//如果没有连接
  2. synchronized(this.state) {//同步代码块,说明连接池必须是线程安全的
  3. if (!this.state.idleConnections.isEmpty()) {//如果没有空闲的连接
  4. idleConnections代表的就是一个ArrayList集合

按照此步骤推理下去
POOLED是使用了自定义的连接池技术
在PooledDataSource类中定义了连接池的默认属性,这些属性可以在主配置文件中修改

protected int poolMaximumActiveConnections = 10;
protected int poolMaximumIdleConnections = 5;
protected int poolMaximumCheckoutTime = 20000;
protected int poolTimeToWait = 20000;
protected int poolMaximumLocalBadConnectionTolerance = 3;

7. 事务

7.1 事务的使用

主要是通过两个方法
commit();
rollback();

7.2 事务分析

mybaits中事务是默认不提交的
需要手动提交事务
也可以设置为自动提交事务
在factory.openSession(true);
创建sqlsession的时候

8. 动态sql语句

8.1 if

判断是否由条件

<select id="findUserByEv" parameterType="user" resultMap="userMap">
        select * from user where 1 = 1
        <if test="userName != null">
            and username = #{userName}
        </if>
        <if test="userBirthday != null">
            and birthday = #{userBirthday}
        </if>
    </select>

注意:其中不能使用&& || 的符号,只能用and or作为条件连接

8.2 where

where主要是去除where 1 = 1这一端,他会根据是否由条件进行拼接字符串

<select id="findUserByEv" parameterType="user" resultMap="userMap">
        select * from user
        <where>
            <if test="userName != null">
                and username = #{userName}
            </if>
            <if test="userSex != null">
                and sex = #{userSex}
            </if>
        </where>
    </select>

8.3 foreach

主要是对集合的遍历

<!--    查询条件中有集合,如何去遍历集合-->
    <select id="findUserOnIds" parameterType="com.itzpx.domain.QueryVo" resultMap="userMap">
        select * from user
        <where>
            <if test="ids != null and ids.size()>0">
                <foreach collection="ids" open="and id in(" close=")" separator="," item="uid">
                    #{uid}
                </foreach>
            </if>
        </where>
    </select>

其中collection=“ids”//表示需要被遍历的集合
open=“and id in(”//表示拼接的开始
close=")"//表示拼接的结束
separator=","//表示分割的符号
item=“uid”//表示从集合中遍历出来的数据
#{uid}//代表取出数据
结果是
select * from user WHERE id in( ? , ? , ? )
提问:为什么要加and id in(
可能是如果where后面如果有条件的话
select * from user WHERE 其他条件 and id in( ? , ? , ? )
如果没有其他条件,mybaits会把and去掉

8.4 sql标签

公共代码片段的抽取

	<sql id="selectId">
        select * from user
    </sql>
    <include refid="selectId"/>

9. 多表操作

9.1 一对多

描述:一个用户,有多个账户
在查询多表时
select * from user,account
这样的语句返回的结果集,关系到多个实体类,所以需要定义
resultMap,来封装结果集
注意:在user实体类中定义account的集合,set\get

<resultMap id="userAccountMap" type="user">
<!--        定义user表字段的封装-->
        <id property="id" column="id"/>
        <result property="userName" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
<!--        定义user表关联的account表的数据封装-->
        <collection property="accounts" column="uid" ofType="account">
            <id property="id" column="aid"/>
            <result property="uid" column="uid"/>
            <result property="money" column="money"/>
        </collection>
    </resultMap>
<!--    配置查询所有-->
    <select id="findAll" resultMap="userAccountMap">
        SELECT
            *
        FROM
	        user AS u
        LEFT JOIN
	        account AS a
        ON
            u.id = a.uid
    </select>

9.2 一对一

描述:一对一其实是多对一,在mybaits中认为一个账户只能对应一个用户,这就是一对一,其实多个账户能对应一个用户,但在mybaits中没有这种说法,所以统一为一对一
查询所有账户的用户信息

<resultMap id="accountUserMap" type="account">
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--和一对多不同,使用的是association 标签-->
        <association property="user" column="uid"  javaType="user">
            <id property="id" column="id"></id>
            <result column="username" property="userName"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </association>
    </resultMap>
<!--    配置查询所有账户的用户信息-->
    <select id="findAll" resultMap="accountUserMap">
        SELECT
            u.*,a.id as aid,a.uid,a.money
        FROM
            account as a,
            user as u
        WHERE
            u.id = a.uid
    </select>

注意:account实体类中,有user对象定义 get/set

9.3 多对多

描述:一个用户可以拥有多个角色,一个角色赋予多个用户,
这种表关系就需要中间表进行连接,中间表主要字段uid,rid,
多对多,写法和一对多写法类似
1.查询用户所拥有的角色信息

<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"/>
    <collection property="roles" column="rid" ofType="role">
        <id property="roleId" column="rid"/>
        <result property="roleName" column="ROLE_NAME"/>
        <result property="roleDesc" column="ROLE_DESC"/>
    </collection>
</resultMap>

<!--    配置查询所有-->
    <select id="findAll" resultMap="userMap">
        SELECT
            u.*,r.id AS rid,r.ROLE_NAME,r.ROLE_DESC
        FROM
	        user AS u
	    LEFT JOIN
	        user_role AS ur
	    ON
	        u.id=ur.uid
	    LEFT JOIN
	        role AS r
	    ON
	        r.id=ur.rid
    </select>

2.反过来查询角色赋予的用户信息

<resultMap id="roleMap" type="role">
    <id property="roleId" column="id"></id>
    <result property="roleName" column="ROLE_NAME"></result>
    <result property="roleDesc" column="ROLE_DESC"></result>
    <collection property="users" column="uid" ofType="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>

<!--    配置查询所有-->
    <select id="findAll" resultMap="roleMap">
        SELECT
            r.*,u.id AS uid,u.username,u.birthday,u.sex,u.address
        FROM
	        role r
	    LEFT JOIN
	        user_role ur
	    ON
	        r.id=ur.rid
	    LEFT JOIN
	        user u
	    ON
	        u.id = ur.uid
    </select>

注意:user实体类中有role集合,role实体类中有user集合

10. 延迟加载

10.1 一对一的延迟加载

查询用户信息时,用户所关联的账户信息在需要的时候加载。
这就是延迟加载
需要在主配置文件中开启延迟加载

<!--    配置开启延迟加载-->
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

查询所有账户

<resultMap id="accountUserMap" type="account">
        <id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <association property="user" column="uid"  javaType="user" select="com.itzpx.dao.IUserDao.findAllById"></association>
    </resultMap>
<!--    配置查询所有账户的用户信息-->
    <select id="findAll" resultMap="accountUserMap">
        SELECT
            *
        FROM
            account
    </select>

select=“com.itzpx.dao.IUserDao.findAllById”
表示的时,调用findAllById方法,根据column="uid"去查询account表
该方法在com.itzpx.dao.IUserDao中

<!--    根据id查询-->
    <select id="findAllById" resultType="user" parameterType="int">
        SELECT
            *
        FROM
            user u
        WHERE
            u.id = #{uid}
    </select>

当查询出来的account列表被使用到的时候,就会调用findAllById,查出用户信息

10.2 一对多的延迟加载

查询user表,

<resultMap id="userAccountMap" type="user">
        <id property="id" column="id"/>
        <result property="userName" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="accounts" column="id" ofType="account" select="com.itzpx.dao.IAccountDao.findAccountById"></collection>
    </resultMap>

<!--    配置查询所有-->
    <select id="findAll" resultMap="userAccountMap">
        SELECT
            *
        FROM
	        user
    </select>
<select id="findAccountById" resultType="account" parameterType="int">
        select * from account where uid = #{uid}
    </select>

11. 缓存

11.1 一级缓存

一、如何使用一级缓存
一级缓存,与sqlSession相关,当重复调用查询方法时,且参数相同,就会到sqlSession中查询一级缓存

User user1 = userDao.findUserById(45);
system.out.prinl(user1);
User user2 = userDao.findUserById(45);
system.out.prinl(user2);
system.out.prinl(user1 == user2);

此时,user1与user2为同一个对象,地址都一样,比较结果为true
二、如何关闭一级缓存
一级缓存关闭,或消失

  1. sqlSession对象消失
  2. sqlSession.clearCache();调用该方法,清空一级缓存
  3. 执行update、insert、delete、commit、等方法

11.2 二级缓存

一、二级缓存的描述
该缓存,由sqlSessionFactory提供,同一个sqlSessionFactory,创建的所有sqlSession共享其缓存。
二、如何开启二级缓存
三步

  1. sqlMapConfig配置文件中开启二级缓存
	<settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
  1. Mapper配置文件中开启二级缓存
	<cache/>
  1. select标签中开启二级缓存,useCache=“true”
<select id="findAll" .... useCache="true">

三、验证二级缓存
在同一个sqlSessionFactory下创建的不同sqlSession,执行同一个方法,比如说执行findAll();
结果:mybaits,只查询一次,其他相同查询都在缓存中拿数据

12. 注解开发

12.1 环境搭建

12.2 单表crud

	//查询所有
    @Select(value="select * from user")
    @Results(id="userMap",value={
            @Result(id=true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "birthday",property = "userBirthday"),
            @Result(column = "sex",property = "userSex"),
            @Result(column = "address",property = "userAddress")
    })
    List<User> findAll();
    //根据ID查询用户
    @Select("select * from user where id = #{id}")
    @ResultMap(value="userMap")
    User findUserById(Integer id);
    //根据ID修改用户
    @Update(value="update user set username = #{userName}," +
            "birthday = #{userBirthday}," +
            "sex = #{userSex}," +
            "address = #{userAddress} " +
            "where id = #{userId}")
    void updateUser(User user);
    //添加一条数据
    @Insert("insert into user (id,username,birthday,sex,address) values (null,#{userName},#{userBirthday},#{userSex},#{userAddress})")
    Integer interUser(User user);

12.3 多表查询

一对一

//查询账户信息,与账户相关的用户信息
    @Select("select * from account")
    @Results(id="accountMap",value={
            @Result(id=true,column="id",property="accountId"),
            @Result(column="uid",property="accountUid"),
            @Result(column="money",property="accountMoney"),
            @Result(one = @One(select = "com.itzpx.dao.IUserDao.findUserById"),column = "uid",property = "user")
    })
    List<Account> findAll();
    //根据uid查询account
    @Select("select * from account where uid = #{uid}")
    @ResultMap(value="accountMap")
    Account findAccountByUid(Integer uid);
//查询所有
    @Select(value="select * from user")
    @Results(id="userMap",value={
            @Result(id=true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "birthday",property = "userBirthday"),
            @Result(column = "sex",property = "userSex"),
            @Result(column = "address",property = "userAddress")
    })
    List<User> findAll();
    //根据ID查询用户
    @Select("select * from user where id = #{id}")
    @ResultMap(value="userMap")
    User findUserById(Integer id);

一对多

//查询用户,及关联的账户
    @Select("select * from user")
    @Results(id="userAccountMap",value={
            @Result(id=true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "birthday",property = "userBirthday"),
            @Result(column = "sex",property = "userSex"),
            @Result(column = "address",property = "userAddress"),
            @Result(many = @Many(select = "com.itzpx.dao.IAccountDao.findAccountByUid"),column = "id",property = "accounts")
    })
    List<User> findUserAndAccount();
//查询账户信息,与账户相关的用户信息
    @Select("select * from account")
    @Results(id="accountMap",value={
            @Result(id=true,column="id",property="accountId"),
            @Result(column="uid",property="accountUid"),
            @Result(column="money",property="accountMoney"),
            @Result(one = @One(select = "com.itzpx.dao.IUserDao.findUserById"),column = "uid",property = "user")
    })
    List<Account> findAll();
    //根据uid查询account
    @Select("select * from account where uid = #{uid}")
    @ResultMap(value="accountMap")
    Account findAccountByUid(Integer uid);

多对多
注意:多对多在sql中需要使用一些技巧,不能使用left join一路连接过去,应该
这样写:id(column = “id”)传递过去,然后根据id查询
@Select(“select * from user where id in (select uid from user_role where rid = #{id})”)

//查询所有
    @Select("select * from role")
    @Results(id="roleMap",value={
            @Result(id=true,column = "id",property="roleId"),
            @Result(column = "ROLE_NAME",property="roleName"),
            @Result(column = "ROLE_DESC",property="roleDesc"),
            @Result(many = @Many(select = "com.itzpx.dao.IUserDao.findUserById2"),column = "id",property = "users")
    })
    List<Role> findAll();
//根据ID查询用户
    @Select("select * from user where id in (select uid from user_role where rid = #{id})")
    @ResultMap(value="userMap")
    List<User> findUserById2(Integer id);

12.4 缓存配置

在dao接口上添加
@CacheNamespace(blocking = true)

13 mybaits留下的知识点

  1. 自定义mybaits
  2. JDNI数据源(基本使用已了解)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值