Mybaits

持久层框架:mybatis(半自动,一般使用于大型项目),hibernate(全自动,适用于小型,简单的项目),spring DataJPA,spring jdbcTemplate(一般不使用)

  • Mybatis框架
    1.什么是mybatis?
    MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJOs(Plain Ordinary Java Object,普通的Java对象)映射成数据库中的记录
    2.MyBatis优缺点
    优点:MyBatis几乎避免了所有的jdbc代码,能自动映射,让程序员把精力放在sql语句上,属于半自动的持久层框架,支持定制sql,可以根据需求编写sql语句,也可以自动生成;
    缺点:sql语句多,还是有缺陷的;
    3.MyBatis开发有三种模式:
    3.1:Dao+DaoImpl(不常用)
    3.1.2:mybatis-configs.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>
        <!--  配置读取db.properteis的标签   -->
        <properties resource="db.properties"></properties>
        <!-- 开发环境  -->
        <environments default="development">
            <environment id="development">
                <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 resource="com/oracle/pojo/User.xml"></mapper>
        </mappers>
    </configuration>
    

    3.1.3:User.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="haha">
        <select id="getUser" parameterType="string" resultType="com.oracle.pojo.User">
            select * from `user` where username = #{username} and `password` = #{password};
        </select>
        <select id="getOne" parameterType="java.lang.Integer" resultType="com.oracle.pojo.User">
            select * from `user` where uid = #{uid}
        </select>
    </mapper>
    

    3.1.4:UserDao

    public interface UserDao {
        //登录
        public User getUserByUsernameAndPassword(String username, String password)throws  Exception;
    
        public User getUserbyUid(Integer uid)throws  Exception;
    }
    

    3.1.5 : UserDaoImpl

    public class UserDaoImpl  implements UserDao{
        @Override
      public User getUserByUsernameAndPassword(String username, String password) throws Exception{
    
            SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
    
            Object obj = sqlSession.selectOne("haha.getUser", user);
    
            //关闭资源
            SqlSessionUtil.close(sqlSession);
    
            return (User)obj;
        }
    
        @Override
        public User getUserbyUid(Integer uid) throws Exception {
    
            SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
            Object obj = sqlSession.selectOne("haha.getOne", uid);
    
            SqlSessionUtil.close(sqlSession);
    
            return (User)obj;
        }
    }
    

    3.1.6 : Test

    public class TestMybatis {
        @Test
        public void test2() throws Exception {
    
            UserDao userDao = new UserDaoImpl();
    
            User user = userDao.getUserbyUid(2);
    
            System.out.println(user);
        }
    
        @Test
        public void test1() throws Exception {
    
            UserDao userDao = new UserDaoImpl();
    
            User user = userDao.getUserByUsernameAndPassword("张三", "123");
    
            System.out.println(user);
        }
    
    }
    

    3.1.7 : SqlSessionFactory封装

    public class SqlSessionUtil {
    	//初始化属性	
        private static SqlSession sqlSession = null;
        private static SqlSessionFactory sqlSessionFactory = null;
    
        //私有构造器
        private SqlSessionUtil(){}
    	//静态块儿加载
        static{
            try {
                InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    	//静态方法获取sqlSession会话
        public static SqlSession getSqlSession(){
            if(sqlSession == null){
                 sqlSession =   sqlSessionFactory.openSession();
            }
            return sqlSession;
        }
    	//关闭资源
        public static void close(SqlSession sqlSession){
            if(sqlSession != null){
                sqlSession.close();
            }
        }
    }
    

    3.2.1:增删改操作
    3.2.1.1添加

     UserDao:
     public int insertUser(User user)throws  Exception;
    
     UserDaoImpl:
     @Override
        public int insertUser(User user) throws Exception {
            SqlSession sqlSession = SqlSessionUtil.getSqlSession();
            int a = sqlSession.insert("user.insertUser", user);
            //手动提交
            sqlSession.commit();
            //关闭资源
            SqlSessionUtil.close(sqlSession);
            return a;
        }
        //user.xml
        <insert id="insertUser">
            insert into `user`(uid,username,password,address)
                 values(null,#{username},#{password},#{address})
    	</insert>
    

    3.2.1.2 修改

    UserDao:
    public int updateUserById(User user)throws Exception;
    
    UserDaoImpl:
    @Override
    public int updateUserById(User user) throws Exception {
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
      int a = sqlSession.update("user.updateUserByUid", user);
      //手动提交
      sqlSession.commit();
    
      SqlSessionUtil.close(sqlSession);
    
      return a;
      //user,xml
      <update id="updateUserByUid">
            update `user` set 
      		    username = #{username} , `password` = #{password} , address = #{address}
                    where uid = #{uid}
      </update>
    }
    

    3.2.1.3 删除

    UserDao:
    public int deleteUserById(Integer id)throws Exception;
    
    UserDaoImpl:
    @Override
    public int deleteUserById(Integer id) throws Exception {
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
      int a = sqlSession.delete("user.deleteUserByUid", id);
      //手动提交
      sqlSession.commit();
    
      SqlSessionUtil.close(sqlSession);
    
      return a;
       //user,xml
       <delete id="deleteUserByUid">
            delete from `user` where uid = #{uid}
       </delete>
    }
    

    3.2.1.4 分页查询

    UserDao:
    public List<User> getUserByLimit(Map<String,Integer> map)throws  Exception;
    
    UserDaoImpl:
    @Override
    public List<User> getUserByLimit(Map<String,Integer> map) throws Exception {
    
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
      List<User> list = sqlSession.selectList("user.getUserByLimit", map);
    
      return list;
        //user,xml
        <select id="getUserByLimit" resultType="user">
    
            select * from `user` limit #{startRow},#{pageSize}
    
    	</select>
    }
    

    测试类:

    @Test
    public void test7() throws Exception {
      Map<String,Integer> map = new HashMap<>();
      Integer pageNo = 2;
      Integer pageSize = 5;
      //map集合的key 是 #{名} value是具体值
      map.put("startRow",(pageNo-1)*pageSize);
      map.put("pageSize",pageSize);
      List<User> list = userDao.getUserByLimit(map);
      for (User user : list) {
        System.out.println(user);
      }
    }
    

    3.2:mapper动态代理开发(重点)
    什么是代理模式?
    用大白话解释就是,程序员不用编写DaoImpl实现类,让MyBatis帮我们就行,那么MyBatis就是一个代理商,帮我们完成实现,体现在代码上就是以后没有daoImpl实现类,只有Dao存在。但是使用代理模式必须满足4个条件:
    1.Dao中的方法名必须和select标签,update,delete,insert标签的id一致;
    2.mapper标签的namespace的值必须是接口的全路径名

    <mapper namespace ="com.oracle.mapper.UserMapper"></mapper>
    

    3.dao方法中的入参的类型必须和select,update,insert标签的parameterType类型一致
    4.dao方法中的返回值类型,必须和select表亲的resultType类型一样
    3.2.1:代码案例
    UserMapper.java

    public interface UserMapper {
        //模糊查询带分页
      public List<User> getUserByLikeWithLimit(@Param("like") String like ,
                                                 @Param("startRow") Integer startRow,
                                                 @Param("pageSize") Integer pageSize);
        //模拟登录
        public User getUserByUserNameAndPassword(@Param("username") String username,
                                                 @Param("password") String password);
        //根据id查询
        public User getUserByUid(Integer uid)throws  Exception;
        ;
        //根据id删除
        public int deleteUserByUid(Integer uid)throws Exception;
    
        //根据id修改
        public int updateUserByUid(User user)throws Exception;
        
        //插入
        public int insertUser(User user)throws Exception;
    
        //模糊查询
        public List<User> getUserByLike(String like)throws Exception;
    
    }
    

    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">
     <!--  namespace命名空间一定是 与 接口全路径名一致 -->
    <mapper namespace="com.oracle.mapper.UserMapper">
      	<!-- id属性的值 一定与 接口中的方法名一致 -->
        <select id="getUserByUserNameAndPassword" resultType="user">
            select * from `user` where username = #{username} and `password` = #{password}
        </select>
    
        <delete id="deleteUserByUid">
             delete from `user` where uid = #{uid}
        </delete>
    
        <select id="getUserByLike" resultType="user">
            select * from `user` where username like concat('%',#{like},'%')
        </select>
    
        <select id="getUserByLikeWithLimit" resultType="user">
            select * from `user` where username like concat('%',#{like},'%')
                 limit #{startRow},#{pageSize}
        </select>
    </mapper>
    

    Test.java

    public class TestUserMapper {
        /**
         * 模糊查询带分页  单元测试
         * @throws Exception
         */
        @Test
        public void test5() throws Exception {
            SqlSession sqlSession = SqlSessionUtil.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            //调用自己的方法
            int startRow = (2-1)*2;
            List<User> list = mapper.getUserByLikeWithLimit("张",startRow,2);
            for (User user : list) {
                System.out.println(user);
            }
            sqlSession.close();
        }
    }	
    

    3.2.2:动态sql

    查询案例: sql的字段片段
    <sql id="userColumns">
            uid,username,`password`,address
    </sql>
    
    修改:
     <update id="updateUserByUid">
            update `user`
              <set>
                  <if test=" username != null and username != ''">
                      username = #{username},
                  </if>
                  <if test=" password != null and password != ''">
                      `password` = #{password},
                  </if>
                  <if test=" address != null and address != ''">
                      address = #{address}
                  </if>
              </set>
              <where>
                  uid =#{uid}
              </where>
        </update>
    
    查询语句的动态sql:
     <select id="getUserByLikeWithLimit" resultType="user">
            select
            <include refid="userColumns"></include>
             from `user`
                <where>
                    <if test=" like != null and like != '' ">
                        username like concat('%',#{like},'%')
                    </if>
                </where>
                <if test="startRow !=null">
                    limit #{startRow},#{pageSize}
                </if>
     </select>
    

    3.2.3批量删除

     //批量删除
     public int deletesByUids(int[] ids)throws Exception;
    
    <!--批量删除-->
    <delete id="deletesByUids">
      delete from `user`
        <where>
          uid in
          <foreach item="a" collection="array" open="(" close=")" separator=",">
            #{a}
          </foreach>
        </where>
    </delete>
    

    3.2.4主键回填

    <insert id="insertUser" useGeneratedKeys="true" keyProperty="uid" >
      <!--
        主键回填技术 这个只适用于 mysql ,如果是oracle数据库就使用
    			(useGeneratedKeys="true" keyProperty="uid")
            <selectKey keyProperty="uid" order="AFTER" resultType="int">
                select LAST_INSERT_ID();
            </selectKey>
            -->
    
            insert into `user`(uid,username,`password`,address) values(null,#{username},#{password},#{address})
    
        </insert>
    
    @Test
    public void test8() throws Exception {
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
      User user = new User();
      user.setUsername("呵呵");
      user.setPassword("123123");
      user.setAddress("上海");
    
      mapper.insertUser(user);
      //在插入成功后 获取 对象的 uid值  这里体现了 主键回填技术
      System.out.println(user.getUid());
    
      sqlSession.commit();
    
      sqlSession.close();
    }
    

    3.3.1:ResultMap标签
    作用1:如果数据库表的字段名和java实体属性名不一致就需要通过resultMap标签来手动映射

    <resultMap id="userResultMap" type="user">
             <!--代表了当前表的 主键
                 column:代表的数据库表的字段名
                 property: 代表的是java类中的属性名
                 javaType: 是java类型的全路径名
                 jdbcType: 数据库的数据类型 ,必须大写字母
              -->
             <id column="uid" property="id" javaType="java.lang.Integer" jdbcType="INTEGER"></id>
             <!--其他字段-->
             <result column="username" property="name"></result>
             <result column="password" property="pwd"></result>
    </resultMap>
    
    <select id="getUserByUserNameAndPassword" resultMap="userResultMap">
            select
            <include refid="userColumns"></include>
            from `user`
            <where>
                <if test="username != null and username != ''">
                    and username =#{username}
                </if>
                <if test="password != null and password != ''">
                    and password = #{password}
                </if>
            </where>
     </select>
    

    作用2:级联查询(表关联查询)
    一对一查询:
    mapper接口:

    public interface CardMapper {
    
        public Card getUserByCode(String code)throws  Exception;
    
    }
    

    CardMapper.xml:

    <resultMap id="cardResultMap" type="card">
            <id column="cid" property="cid"></id>
            <result column="number" property="number"></result>
            <result column="uid" property="uid"></result>
            <!--user 跟car但是 一对一
                     property属性代表   Card实体类中的 user属性名
                     column代表card表的 外键字段
                     select 去另一个空间做另一个表的查询操作,好处解耦
             -->
            <association property="user" column="uid" 
                         select="com.oracle.mapper.UserMapper.getUserByUid">
            </association>
    </resultMap>
    
    <!--如果你不会写多表查询的时候 -->
    <select id="getUserByCode" resultMap="cardResultMap">
      select cid,number,uid from card where number = #{number}
    </select>
    

    UserMapper.xml:

    <mapper namespace="com.oracle.mapper.UserMapper">
      <!--这个标签 是为了 级联查询的 -->
      <select id="getUserByUid" resultMap="userResultMap">
        select * from `user` where uid = #{uid}
      </select>
    </mapper>
    

    单元测试:

    @Test
    public void test() throws Exception {
    
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
      CardMapper mapper = sqlSession.getMapper(CardMapper.class);
    
      Card card = mapper.getUserByCode("110");
    
      System.out.println(card);
    
      User user = card.getUser();
    
      System.out.println(user);
    
    }
    

    一对多级联查询:
    UserMapper:

     //根据用户id 查询订单
    public User getOrdersByUid(Integer uid)throws Exception;
    

    UserMapper.xml

    <mapper namespace="com.oracle.mapper.UserMapper">
    <resultMap id="userResultMap" type="user">
             <!--代表了当前表的 主键
                 column:代表的数据库表的字段名
                 property: 代表的是java类中的属性名
                 javaType: 是java类型的全路径名
                 jdbcType: 数据库的数据类型 ,必须大写字母
              -->
             <id column="uid" property="id" javaType="java.lang.Integer" jdbcType="INTEGER"></id>
             <!--其他字段-->
             <result column="username" property="name"></result>
             <result column="password" property="pwd"></result>
    
             <!--多方 orders
                propertyL: user实体类中的 orders 属性名
                column: 当前uid主键 是 order表的外键
                ofType: User实体类中集合的泛型 order类型
    
             -->
             <collection property="orders" column="uid" ofType="order"
                            select="com.oracle.mapper.OrderMapper.getOrdersByUid">
    
             </collection>
     </resultMap>
    
        <!-- 根据 用户 uid 查询所有 订单  -->
        <select id="getOrdersByUid" resultMap="userResultMap">
            select * from `user` where uid = #{uid}
        </select>
    </mapper>
    

    OrderMapper.xml

    <select id="getOrdersByUid" resultType="order">
      	select * from `order` where uid = #{uid}
    </select>
    

    测试类:

     @Test
    public void test9() throws Exception {
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
      User user = mapper.getOrdersByUid(14);
    
      List<Order> orders = user.getOrders();
    
      for (Order order : orders) {
        System.out.println(order);
      }
    }
    

    根据订单编号找人:
    OrderMapper接口:

    public interface OrderMapper {
        //根据订单找人
        public Order getUserByCode(String code)throws  Exception;
    
    }
    

    OrderMapper.xml

    <mapper namespace="com.oracle.mapper.OrderMapper">
        <resultMap id="orderResultMap" type="order">
            <!--user 的 一方-->
            <association property="user" column="uid"
                         select="com.oracle.mapper.UserMapper.getUserByUid">
            </association>
        </resultMap>
        <select id="getOrdersByUid" resultType="order">
            select * from `order` where uid = #{uid}
        </select>
    </mapper>
    

    UserMapper.xml

    <mapper namespace="com.oracle.mapper.UserMapper">
    	<!--这个标签 是为了 级联查询的 -->
        <select id="getUserByUid" resultMap="userResultMap">
              select * from `user` where uid = #{uid}
        </select>
    </mapper>
    

    测试类:

    @Test
    public void test1() throws Exception {
    1
      SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    
      OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    
      Order order = orderMapper.getUserByCode("DFJ23");
    
      User user = order.getUser();
    
      System.out.println(user);
    
    }
    

    多对多:
    OrderMapper.java

    //根据订单编号查询商品
        public Order getProductByCode(String code)throws Exception;
    

    OrderMapper.xml

    <mapper namespace="com.oracle.mapper.OrderMapper">
    
        <resultMap id="OrderResultMapper" type="order">
            <id column="oid" property="oid"></id>
    
            <association property="user" column="uid" 							           		 		select="com.oracle.mapper.UserMapper.getUserByUid">
            </association>
    
            <collection property="products" column="oid" ofType="product"
                select="com.oracle.mapper.ProductMapper.getProductByOid">							</collection>
        </resultMap>
    
        //根据订单编号查询订单oid 再根据多表itms查对应的pid
        <select id="getUserByCode" resultMap="OrderResultMapper">
            select * from `order` where code =#{code}
        </select>
    	//根据多个oid找多个订单
        <select id="getOrderByPid" resultMap="OrderResultMapper">
            select * from order_product_item opi inner  join `order` o on opi.oid = o.oid
                where opi.pid =#{pid}
        </select>
    
    </mapper>
    

    ProductMapper.java

        //跟据商品名字查订单
        public Product  getOrderByProductName(String productName)throws Exception;
    

    ProductMapper.xml

    <mapper namespace="com.oracle.mapper.ProductMapper">
    
        <resultMap id="ProductResultMap" type="product">
            <id property="pid" column="pid"></id>
    
            <collection property="orders" column="pid" ofType="order"
                        select="com.oracle.mapper.OrderMapper.getOrderByPid"></collection>
        </resultMap>
    	//根据多个pid找多个商品
        <select id="getProductByOid" resultMap="ProductResultMap">
            select * from order_product_item opi inner join product p on opi.pid = p.pid
                    where oid=#{oid}
        </select>
    	//根据商品名称查询订单pid 再根据多表itms查对应的oid
        <select id="getOrderByProductName" resultMap="ProductResultMap">
            select * from `product` where produceName=#{productName}
        </select>
    
    </mapper>
    

    3.3 注解开发(不太推荐,耦合度高)

    public interface UserMapper {
    
    @Select("select * from `user` where username =#{username} and password = #{password}")
      public User getUserByUserNameAndPassword(@Param("username") String username,
                                               @Param("password") String password)throws Exception;
    
    @Insert("insert into user(uid,username,password,address) values(null,#{username},#{password},#{address})")
      @SelectKey(statement = "select LAST_INSERT_ID()",keyProperty="nameId", before=true, resultType=int.class)
      public void insertUser(User user)throws Exception;
       
    }
    

    3.4日志
    mybatis的日志有两种形式,输出mybatis的执行过成,包括sql语句的执行
    1.使用mybatis默认的日志框架:不需要导入jar包

    <!-- 运行参数 -->
        <settings>
            <!-- mybatis 默认的日志  -->
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    

    2.使用LOG4J日志框架,需要导入jar包和log4j.properties日志文件

    <!-- 运行参数 -->
    <settings>
      <!-- mybatis 默认的日志  -->
      <setting name="logImpl" value="LOG4J"/>
    </settings>
    

    LOG4J文件,放在src目录上:

    #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
    log4j.rootLogger=DEBUG,console,file
    
    #控制台输出的相关设置
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    
    #文件输出的相关设置
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/shun.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    
    #日志输出级别
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    

    3.5 延迟加载(按需加载)

    <settings>
            <!-- mybatis 默认的日志  -->
            <setting name="logImpl" value="LOG4J"/>
            <!-- 设置延迟加载吗  设置 true-->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!-- 积极加载吗  不滴-->
            <setting name="aggressiveLazyLoading" value="false"/>
            <setting name="lazyLoadTriggerMethods" value=","/>
     </settings>
    

    3.6mybatis的分页插件:
    mybatis采用分页插件时,sql不需要写limit分页了,但是需要导入jar包
    1.pagehelpher-5.1.1.jar
    2.jsqlparser-1.0.jar

    <?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>
      <!--插件 -->
      <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
          <!-- 指定数据库版本名 是什么 -->
          <property name="helpDialect" value="mysql"/>
          <!-- 合理化 true:  如果pageNum < 1 ,他给你返回第一页 ,如果pageNum > totalPage 返回最后一页
               合理化 false: 如果pageNum < 1 ,返回 空 ,如果pageNum> totalPage 返回 空
           -->
          <property name="seasonable" value="true"/>
        </plugin>
      </plugins>
    </configuration>
    
    @Test
    public void test10() throws Exception {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //分页插件对象
        Integer pageNum = 1;
        Integer pageSize = 5;
        PageHelper.startPage(pageNum,pageSize);
        List<User> list = mapper.getAll(); //sql 语句中 没有 limit 关键字
        PageInfo  pageInfo = new PageInfo<>(list);
        System.out.println("当前页: "+pageInfo.getPageNum());
        System.out.println("页大小: "+pageInfo.getPageSize());
        System.out.println("总记录数: "+pageInfo.getTotal());
        System.out.println("总页数: "+pageInfo.getPages());
        //从PageInfo对象中获取的数据
        List users = pageInfo.getList();
        for (Object user : users) {
          System.out.println(user);
        }
    }
    

    3.7 mybatis的缓存
    一级缓存:mybatis默认的就是一级缓存,默认开启的,是SqlSession会话级别的缓存,所有sqlSession共享,在执行同一个sql语句时,如果缓存去没有数据,那么就回数据库查询,第二次来,发现缓存区有数据就直接从遗迹缓存中获取数据的,也就是说执行了一次sql语句,出现了两次结果。如果执行了insert、update、delete会清空一级缓存,避免出现脏读。

    [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
    [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1426329391.
    [com.oracle.mapper.UserMapper.getOrdersByUid]-==>  Preparing: select * from `user` where uid = ?
    [com.oracle.mapper.UserMapper.getOrdersByUid]-==> Parameters: 14(Integer)
    [com.oracle.mapper.UserMapper.getOrdersByUid]-<==      Total: 1
    User{uid=14, name='kakakaka', pwd='123123', address='12312312312'}
    User{uid=14, name='kakakaka', pwd='123123', address='12312312312'}  执行一次sql语句,出现两次结果
    

    二级缓存:
    二级缓存时namespace级别的,也就是mapper级别的缓存,多个mapper级别的缓存不共享,但是可以使用cache-ref namespace="公共空间"的这个标签让其共享,我们在开启二级缓存时,需要在全局配置文件中添加

    <settings>
      <!-- 开启二级缓存的全局开关 -->
      <setting name="cacheEnabled" value="true"/>
      <settings>
    
    <cache
      eviction="FIFO"
      flushInterval="60000"
      size="512"
      readOnly="true"/>
    

    测试结果:

    [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
    [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 1256440269.
    [com.oracle.mapper.UserMapper.getOrdersByUid]-==>  Preparing: select * from `user` where uid = ?
    [com.oracle.mapper.UserMapper.getOrdersByUid]-==> Parameters: 14(Integer)
    [com.oracle.mapper.UserMapper.getOrdersByUid]-<==      Total: 1
    User{uid=14, name='kakakaka', pwd='123123', address='12312312312'}
    [com.oracle.mapper.UserMapper]-Cache Hit Ratio [com.oracle.mapper.UserMapper]: 0.0
    User{uid=14, name='kakakaka', pwd='123123', address='12312312312'}
    

    总结:mybatis的缓存加载顺序是,二级缓存优先加载,如果没有在加载一级缓存,mybatis的缓存在分布式架构中不可用,容易出现脏读,实战中使用redis最好

  • Mybatis的逆向工程

    <generatorConfiguration>
    	<context id="testTables" targetRuntime="MyBatis3">
    	
    		<!-- JavaBean 实现 序列化 接口 -->
    		<plugin type="org.mybatis.generator.plugins.SerializablePlugin">
    		</plugin>
    		<!-- genenat entity时,生成toString -->
            <plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
            <!-- 自定义物理分页  可生成支持Mysql数据的limit  不支持Oracle -->
            <plugin type="org.mybatis.generator.plugins.page.PaginationPlugin" />
            <!-- 自定义查询指定字段  -->
            <plugin type="org.mybatis.generator.plugins.field.FieldsPlugin" />	
    		<!-- 此处是将Example改名为Criteria 当然 想改成什么都行~    -->      
            <plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">  
    	        <property name="searchString" value="Example$" />
    	        <!-- 替换后
    	        <property name="replaceString" value="Criteria" />  
    	         -->
    	        <property name="replaceString" value="Query" />
            </plugin>  
    		<!-- 此处是将UserMapper.xml改名为UserDao.xml 当然 想改成什么都行~ -->        
            <plugin type="org.mybatis.generator.plugins.rename.RenameSqlMapperPlugin">  
    	        <property name="searchString" value="Mapper" />
    	        <property name="replaceString" value="Mapper" />
            </plugin>  
             
    		<!-- 此处是将UserMapper改名为UserDao 接口 当然 想改成什么都行~  -->        
            <plugin type="org.mybatis.generator.plugins.rename.RenameJavaMapperPlugin">  
    	        <property name="searchString" value="Mapper$" />
    	        <property name="replaceString" value="Mapper" />
            </plugin>  
    		<commentGenerator type="org.mybatis.generator.plugins.comment.MyCommentGenerator">
    			<!-- 是否去除自动生成的注释 true:是 : false:否 
    			<property name="suppressAllComments" value="true" />
    			-->
    		</commentGenerator>
    		<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
    		<jdbcConnection driverClass="com.mysql.jdbc.Driver"
    			connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root"
    			password="root">
    		</jdbcConnection>
    		<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
    			connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" 
    			userId="yycg"
    			password="yycg">
    		</jdbcConnection> -->
    
    		<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 
    			NUMERIC 类型解析为java.math.BigDecimal -->
    		<javaTypeResolver>
    			<property name="forceBigDecimals" value="false" />
    		</javaTypeResolver>
    		<!-- targetProject:生成POJO类的位置 -->
    		<javaModelGenerator targetPackage="com.oracle.pojo"
    			targetProject=".\src">
    			<!-- enableSubPackages:是否让schema作为包的后缀 -->
    			<property name="enableSubPackages" value="false" />
    			<!-- 从数据库返回的值被清理前后的空格 -->
    			<property name="trimStrings" value="true" />
    		</javaModelGenerator>
    
            <!-- targetProject:mapper映射文件生成的位置 -->
    		<sqlMapGenerator targetPackage="com.oracle.mapper" 
    			targetProject=".\src">
    			<!-- enableSubPackages:是否让schema作为包的后缀 -->
    			<property name="enableSubPackages" value="false" />
    		</sqlMapGenerator>
    		<!-- targetPackage:mapper接口生成的位置 -->
    		<javaClientGenerator type="XMLMAPPER"
    			targetPackage="com.oracle.mapper" 
    			targetProject=".\src">
    			<!-- enableSubPackages:是否让schema作为包的后缀 -->
    			<property name="enableSubPackages" value="true" />
    		</javaClientGenerator>
    		
    		<!-- 指定数据库表 -->
    		<!-- 用户模块表  -->
    		<table schema="" tableName="user" domainObjectName="User">
    		</table>
    		<table schema="" tableName="card" domainObjectName="Card"/>
    		<table schema="" tableName="order" domainObjectName="Order"/>
    		<table schema="" tableName="product" domainObjectName="Product"/>
    	</context>
    </generatorConfiguration>
    

    service层:

    public interface UserService {
    	
    	public User login(String username,String password);
    
    	public void insertUser(User user);
    	
    	public void deleteUserById(Integer uid);
    	
    	public void deletesUsersByUid(int[] ids);
    	
    	public void updateUserByUid(User user);
    	
    	public List<User> getAll();
    	
    	public List<User> getUserByLikeWithLimit(String like ,Integer paegNo,Integer pageSize);
    	
    }
    

    serviceImpl实现类:

    public class UserServiceImpl implements UserService {
    
    	@Override
    	public User login(String username, String password) {
    		SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    		UserQuery example = new UserQuery();
    		//参数赋值
    		Criteria c = example.createCriteria();
    		c.andUsernameEqualTo(username);
    		c.andPasswordEqualTo(password);
    		List<User> list = mapper.selectByExample(example);
    		return list.get(0);
    	}
    
    	@Override
    	public void insertUser(User user) {
    		SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    		int a = mapper.insertSelective(user);
    		sqlSession.commit();
    		sqlSession.close();
    		
    	}
    
    	@Override
    	public void deleteUserById(Integer uid) {
    		SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    		int a = mapper.deleteByPrimaryKey(uid);
    	}
    
    	@Override
    	public void deletesUsersByUid(int[] ids) {
    
    
    	}
    
    	@Override
    	public void updateUserByUid(User user) {
    		SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    		mapper.updateByPrimaryKeySelective(user);
    	}
    
    	@Override
    	public List<User> getAll() {
    		SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    		UserQuery example = new UserQuery();
    		List<User> list = mapper.selectByExample(example);
    		return list;
    	}
    
    	@Override
    	public List<User> getUserByLikeWithLimit(String like, Integer pageNo, Integer pageSize) {
    		SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    		UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    		UserQuery example = new UserQuery();
    		//赋值页码 和  页大小即可
    		example.setPageNo(pageNo);
    		example.setPageSize(pageSize);
    			//设置条件
    		Criteria c = example.createCriteria();
    		c.andUsernameLike("%" + like +"%");
    		List<User> list = mapper.selectByExample(example);
    		return list;
    	}
    }
    

    单元测试:

    public class TestUser {
    	 
    	UserService userService = new UserServiceImpl();
    	
    	@Test
    	public void test7(){
    		String like = "呵";
    		Integer pageNo = 1;
    		Integer pageSize = 5;
    		List<User> list = userService.getUserByLikeWithLimit(like, pageNo, pageSize);
    		for (User user : list) {
    			System.out.println(user);
    		}
    	}
    	
    	
    	@Test
    	public void test6(){
    		List<User> list = userService.getAll();
    		for (User user : list) {
    			System.out.println(user);
    		}
    	}
    	
    	@Test
    	public void test5(){
    		User user =new User();
    		user.setUid(102);
    		user.setAddress("小草屋");
    		userService.updateUserByUid(user);
    	}
    	
    	
    	@Test
    	public void test4(){
    		userService.deleteUserById(15);
    	}
    	
    	@Test
    	public void test2(){
    		User user = new User();
    		user.setUsername("诸葛亮");
    		user.setPassword("111");
    		userService.insertUser(user);
    	}
    	
    	@Test
    	public void test1(){
    		User user = userService.login("关羽", "123");
    		System.out.println(user);
    	}
    	
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值