原生mybaits学习笔记

简介

操作数据库

maven引入

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>

核心配置文件

SqlMapConfig.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>
    <!--resource:加载外部配置文件,外部配置会替换内部配置-->
    <properties resource="db.properties">
        <!--配置内部属性-->
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbc.username" value="root"/>
    </properties>
    
    <!--配置类型别名-->
    <typeAliases>
        <package name="com.XXX.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <!--数据库配置-->
                <property name="driver" value="${driver}" />
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatisdb?characterEncoding=utf8" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>

    <!--SqlMapConfig.xml:就是MyBatis的核心配置文件-->
    <!--配置需要加载的Mapper.xml映射文件-->
    <mappers>
        <!--resource:需要加载的映射文件的文件地址-->
        <!--<mapper resource="mapper/UserMapper.xml"/>-->

        <!--使用类加载的方式加载资源-->
        <!--前提1:名字一致,前提2:目录一致(在一起)-->
        <!--<mapper class="com.XXX.mapper.UserDao"/>-->

        <!--package使用包扫描的方式加载资源-->
        <!--前提1:名字一致,前提2:目录一致(在一起)-->
        <package name="com.XXX.mapper"/>
    </mappers>
</configuration>    

方式一(简单)

直接使用配置文件

配置

mapper/UserMapper.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.XXX.mapper.ProductMapper">
    <select id="queryProductByPid" parameterType="int" resultType="com.XXX.pojo.Product">
        SELECT * from product WHERE pid=#{pid};
    </select>
</mapper>

操作

List<Product> list = sqlSession.selectList("queryProductByPid", 1);

方式二(old)

创建接口

PersonMapper.java

public interface ProductMapper {

    List<Product> queryProductByPid(int pid);

}

配置mapper.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.XXX.mapper.ProductMapper">
    <select id="queryProductByPid" parameterType="int" resultType="com.XXX.pojo.Product">
        SELECT * from product WHERE pid=#{pid};
    </select>
</mapper>

实现接口

ProductMapperImpl

public class ProductMapperImpl implements ProductMapper {
    private SqlSessionFactory sqlSessionFactory;

    public ProductMapperImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public List<Product> queryProductByPid(int pid) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<Product> list = sqlSession.selectList("queryProductByPid", pid);
        return list;
    }
}

操作

ProductMapper mapper = new ProductMapperImpl(sessionFactory);
List<Product> products = mapper.queryProductByPid(1);

方式三(常用)

创建接口

PersonMapper.java

public interface ProductMapper {

    List<Product> queryProductByPid(int pid);

}

配置mapper.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.XXX.mapper.UserDao">

    <!-- #{} 是传参数,防止sql注入 -->
    <!-- ${} 是拼接,用于非参数的拼接 -->
    
    <!--根据id查询-->
    <select id="queryUserById" parameterType="int" resultType="UsEr">
        select * FROM user WHERE  id=#{id}
    </select>

    <!--根据用户名模糊查询,传入的时候加:%!!!-->
    <select id="queryUserByUsername" parameterType="string" resultType="com.XXX.pojo.User">
        select * from USER WHERE username like #{username}
    </select>

    <!--新增-->
    <insert id="saveUser" parameterType="com.XXX.pojo.User">
        <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
            SELECT last_insert_id()
        </selectKey>
        insert into USER (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address});
    </insert>

</mapper>

操作

SqlSession sqlSession = sessionFactory.openSession();
ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
List<Product> products = mapper.queryProductByPid(1);
System.out.println(products);

配置详解

传入参数

<!--传入复杂参数-->
<select id="selectProduct2" parameterType="ProductVo" resultMap="product2">
    SELECT * from product where pid>#{product.pid};
</select>

接收参数

<!--传出参数和数据库列名不一致-->
<resultMap id="product2" type="product2" autoMapping="true">
    <id column="pid" property="pid"/>
    <result column="category_id" property="cid"/>
</resultMap>
<select id="selectProduct2" parameterType="ProductVo" resultMap="product2">
    SELECT * from product where pid>#{product.pid};
</select>

判断循环

<!--if判断-->
<select id="queryUserByUsernameAndSex" parameterType="user" resultType="user">
    SELECT <include refid="fields"/> FROM `user`
    <where>
        <if test="sex!=null and sex!=''">
            AND sex=#{sex}
        </if>
        <if test="username!=null and username!=''">
            AND username LIKE #{username}
        </if>
    </where>
</select>

<!--代码片段-->
<sql id="fields">
    id,username,birthday,sex,address
</sql>

<!--foreach-->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
    SELECT <include refid="fields"/> FROM `user`
    <where>
        <foreach collection="ids" item="item" open="id in (" close=")" separator=",">
            #{item}
        </foreach>
    </where>
</select>

一对一查询

<!--一对一查询,查询账号和对应的用户数据,方案一-->
<select id="queryAccountUserAll" resultType="accountUser">
    SELECT a.*,u.username,u.address FROM account a LEFT JOIN `user` u ON a.UID=u.id
</select>

<!--配置一对一查询方案二的ResultMap-->
<resultMap id="accountResultMap" type="account" autoMapping="true">
    <!--配置的Account的主键-->
    <id property="id" column="id"/>
    <result property="uid" column="uid"/>
    
    <association property="user" javaType="user" autoMapping="true">
        <id property="id" column="uid"/>
        <result property="username" column="username"/>

    </association>

</resultMap>

<!--一对一查询,查询账号和对应的用户数据,方案二(使用ResultMap)-->
<select id="queryAccountAll" resultMap="accountResultMap">
    SELECT a.*,u.username,u.address FROM account a LEFT JOIN `user` u ON a.UID=u.id
</select>

一对多查询

<!--配置ResultMap-->
<resultMap id="userResultMap" type="user" autoMapping="true">
    <id property="id" column="id"/>
    <collection property="accounts" ofType="Account" autoMapping="true">
        <id property="id" column="aid"/>
    </collection>

</resultMap>

<!--查询所有的用户数据,使用一对多的方式,查询该用户的所有账号信息-->
<select id="queryUserAll" resultMap="userResultMap">
    SELECT u.*,a.id aid,a.money FROM user u LEFT JOIN account a ON u.id=a.uid
</select>

延迟加载

  • 先再总配置里面打开
<settings>
    <!--开启延时加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false" />
</settings>
  • 再在mapper.xml里面配置column和select
<!--一对一-->
<association property="user" javaType="user" column="uid"
    select="com.alvin.mapper.UserMapper.queryUserById"></association>
<!--一对多-->
<collection property="accounts" ofType="Account" column="id"
    select="com.alvin.mapper.AccountMapper.queryAccountByUid"></collection>

缓存

一级缓存

作用于具体sqlSession

默认开启

二级缓存

作用于指定mapper文件,如果在account.mapper里面操作user,有可能会影响user表的操作,所以一般不用。

  • 核心配置文件(默认为true可以不设置)
<!--全局打开二级缓存-->
<setting name="cacheEnabled" value="true"/>
  • 普通mapper.xml
<!--局部打开二级缓存-->
<cache/>

<!--useCache="true"打开某个select缓存-->
<select id="queryUserById" parameterType="int" resultType="user" useCache="true">
    select * from user where id=#{id}
</select>

全注解开发

@Select("select * from user where id=#{id}")
public User queryUserById(Integer id);

@Select("select * from user")
public List<User> queryUserAll();

//@SelectKey:扩展,配置主键返回,statement:用来配置查询主键数据的sql
@SelectKey(statement = "select last_insert_id()", keyProperty = "id"
        , keyColumn = "id", before = false, resultType = Integer.class)
@Insert("insert into user (username,birthday,sex,address) " +
        "values (#{username},#{birthday},#{sex},#{address})")
public void saveUser(User user);

@Update("update user set username=#{username} where id=#{id}")
public void updateUserById(User user);

@Delete("delete from user where id=#{id}")
public void deleteUserById(Integer id);

//扩展:如果要使用动态sql的标签,需要给最终的sql语句用<script>标签进行包裹
@Select("<script>" +
        "SELECT * FROM USER
" +
        "<where>
" +
        "    <if test="sex!=null and sex!=''">
" +
        "        AND sex=#{sex}
" +
        "    </if>
" +
        "    <if test="username!=null and username!=''">
" +
        "        AND username like #{username}
" +
        "    </if>
" +
        "</where>" +
        "</script>")
public List<User> queryUserByUsernameAndSex(User user);


//查询所有的用户数据,使用延时加载的方式获取该用户的账户数据
//@Results:相当于在配置ResultMap
//@Result:相当于配置ResultMap里面的<id>和<result>标签
//@Result里面的id属性:就是这个配置是否是主键,如果是true,就代表这是主键,如果是false就不是主键
//@Result里面的property属性:就是配置对应的pojo的哪一个属性
//@Result里面的column属性:配置对应的数据库结果集的那一列,
// 如果是一对一和一对多,这里配置的就是延时加载的时候,需要使用的查询参数
//本例中延时加载账户的用户数据,就需要通过uid进行查询
//@Result注解里面没有ofType,而xml映射文件中有ofType,注解既然没有,就省略不写
//@Result里面的javaType就是属性的类型
//@Result里面的one配置的是一对一的延时加载,里面需要填写的是@One注解
//@One里面的select属性是配置延时加载需要执行的方法,和映射文件中延时加载的select属性配置的效果是一样
//@One里面的fetchType属性是配置是否使用延时加载,FetchType.LAZY代表使用延时加载
@Select("select * from user")
@Results({
        @Result(id = true,property = "id",column = "id"),
        @Result(property = "username",column = "username"),
        @Result(property = "birthday",column = "birthday"),
        @Result(property = "sex",column = "sex"),
        @Result(property = "address",column = "address"),
        @Result(property = "accounts",column = "id",
        many = @Many(select = "com.alvin.mapper.AccountMapper.queryAccountByUid"))
})
public List<User> queryUserAccountAll();

//查询所有的账户数据,同时延时加载用户数据
@Select("select * from account")
@Results({
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "uid", column = "uid"),
        @Result(property = "money", column = "money"),
        @Result(property = "user", column = "uid", javaType = User.class,
                one = @One(select = "com.alvin.mapper.UserMapper.queryUserById")),
})
public List<Account> queryAccountUserAll();

//支持用户的延时加载账户信息,所编写的方法
@Select("select * from Account where uid=#{uid}")
public List<Account> queryAccountByUid(Integer uid);
原文地址:https://www.cnblogs.com/birdofparadise/p/10012278.html