java 是最全面成熟的语言,它的思想可以扩展到以后学习的任何编程语言

1,mybatis

持久层,解决jdbc的繁琐,

--1,dome

创建maven项目,导入org.mybatis jar包

.1 ,配置mybatis-config.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核心配置文件-->

    <properties resource="db.properties">
    	<!--引入外部配置文件
    	编写一个配置文件
        db.properties

        driver=com.mysql.jdbc.Driver
        url=jdbc:mysql://localhost:3306/mybatis?	useSSL=true&useUnicode=true&characterEncoding=UTF-8
        username=root
        password=123456
            -->
        <property name=
            "username" value="root"/>
        <property name="pwd" value="11111"/>
    </properties>


    <typeAliases>
      <!--可以给实体类起别名-->
            可以在实体类上用注解起别名 更方便
            @Alias("user")
            public class User {}
        <typeAlias type="com.kuang.pojo.User" alias="User"/>
    </typeAliases>
    <typeAliases>
    	整个com.kuang.pojo包下的所有实体类默认为首字母小写别名
        <package name="com.kuang.pojo"/>
    </typeAliases>

<configuration>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/> Mybatis默认的事务管理器就是 JDBC ,
    	
            <dataSource type="POOLED">  Mybatis默认的资源管理器  连接池 : POOLED
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
<!--每一个Mapper.XML都需要在Mybatis核心配置文件中注册!-->
<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
     mapper属性
	class="com.kuang.dao.UserMapper"  也可以是对应接口 条件 接口和他的Mapper配置文件必须同名!
	接口和他的Mapper配置文件必须在同一个包下
</mappers>

</configuration>
@

.2 ,编写mybatis工具类

@ 获取sqlSessionFactory对象

 String resource = "mybatis-config.xml";        
InputStream inputStream = Resources.getResourceAsStream(resource);           sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

@ 获取数据库连接对象

public static SqlSession  getSqlSession(){    
return sqlSessionFactory.openSession();    }

.3 编写数据库对应的实体类

package com.kuang.pojo;

//实体类
public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}


.4 编写接口,声明对应的增删改查方法

public interface UserDao {
    List<User> getUserList();
}

.5 编写接口对应的mapper.xml 配置对应的增删改查方法 一个实体类接口对应一个 mapper.xml文件 并且一定要到mybaits-config.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=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.kuang.dao.UserDao">

<!--select查询语句-->
   <select id="getUserList" resultType="com.kuang.pojo.User">
    	<!--select属性解析 
		id="getUserList" 一定和接口的方法名对应,
    	resultType="com.kuang.pojo.User"  sql执行返回结果一般对应一个实体类
    	parameterType,参数如果就一个且是基本数据类型,就不用指定,会自动推断。
    	resultMap="UserMap"  遇到实体类属性名于数据库表字段名不一致 resultMap结果集映射
    	复杂的参数建议用map(万能)字段名要和key名一致
        <insert id="addUser" parameterType="map">
            insert into mybatis.user (id, pwd) values (#{userid},#{passWord});
        </insert>
    	如果是对象类型,在拼接数据库语句时,字段名要和类的属性名一致
        <insert id="addUser" parameterType="com.kuang.pojo.User">
            insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
        </insert>
        模糊查询
       Java代码执行的时候,传递通配符 % %
		List<User> userList = mapper.getUserLike("%李%");这种做法通常比较安全
  		<insert id="selectUser" parameterType="String">
           select * from mybatis.user where name like #{value}
        </insert>
		-->
       select * from mybatis.user
        遇到实体类属性名于数据库表字段名不一致
		1,sql语句起别名
            <select id="getUserById" resultType="com.kuang.pojo.User">
            select id,name,pwd as password from mybatis.user where id = #{id}
            </select>
        2,resultMap结果集映射
         <select id="getUserById" resultMap="UserMap">
        	select * from mybatis.user where id = #{id}
   		 </select>
   </select>
	<!--结果集映射-->
    <resultMap id="UserMap" type="User">
        <!--column数据库中的字段,property实体类中的属性-->
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>
</mapper>

.6 测试功能

@Test
public void test(){
    //第一步:获得SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();


    //方式一:getMapper
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    List<User> userList = userDao.getUserList();

    for (User user : userList) {
        System.out.println(user);
    }
    //关闭SqlSession
    sqlSession.close();
}


2,面向注解开发 框架之重点 ,不仅仅是mybatis 其他框架也是

.1 接口上实现

@Select("select * from user")
List<User> getUsers();
 // 方法存在多个参数,所有的参数前面必须加上 @Param("id")注解
    关于@Param() 注解
    基本类型的参数或者String类型,需要加上
    引用类型不需要加
    如果只有一个基本类型的话,可以忽略,但是建议大家都加上!
    我们在SQL中引用的就是我们这里的 @Param() 中设定的属性名!
    @Select("select * from user where id = #{id}")
    User getUserByID(@Param("id") int id);
	@Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})")
    int addUser(User user);
    @Update("update user set name=#{name},pwd=#{password} where id = #{id}")
    int updateUser(User user);
    @Delete("delete from user where id = #{uid}")
    int deleteUser(@Param("uid") int id);
	#{} ${} 区别
	#{} 安全 ,预编译之后嵌入
    ${} 直接拼接  不安全  
        各有用处

.2 核心配置文件中绑定接口!(只能用class属性

<!--绑定接口-->
<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>


3,Lombok 简化代码工具类
在实体类上加注解即可!
@Data:无参构造,get、set、tostring、hashcode,equals
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@ToString
@Getter
自动生成一些常用方法  非常建议使用
4,表关联时的复杂sql

.1多对一处理

<!--
    思路:
        1. 查询所有的学生信息
        2. 根据查询出来的学生的tid,寻找对应的老师!  子查询
    -->
	复杂的结果用 resultMap

1.1按照查询嵌套处理
<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>

<resultMap id="StudentTeacher" type="Student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--复杂的属性,我们需要单独处理 对象: association 集合: collection -->
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    association属性
	property="teacher"  type="Student"中的teacher 属性
    column="tid" 外键
    javaType="Teacher" type="Student"中的teacher 属性的类型
    select="getTeacher" 对应mapper中的 sql语句
</resultMap>

<select id="getTeacher" resultType="Teacher">
    select * from teacher where id = #{id}
</select>
1.2按照结果嵌套处理

<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
    select s.id sid,s.name sname,t.name tname
    from student s,teacher t
    where s.tid = t.id;
</select>

<resultMap id="StudentTeacher2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>


.2 一对多处理

1.按照结果嵌套处理

    <!--按结果嵌套查询-->
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid, s.name sname, t.name tname,t.id tid
        from student s,teacher t
        where s.tid = t.id and t.id = #{tid}
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--复杂的属性,我们需要单独处理 对象: association 集合: collection
        javaType="" 指定属性的类型!
        集合中的泛型信息,我们使用ofType获取
        -->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
2,按照查询嵌套处理
        <select id="getTeacher2" resultMap="TeacherStudent2">
            select * from mybatis.teacher where id = #{tid}
        </select>

        <resultMap id="TeacherStudent2" type="Teacher">
            <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
        </resultMap>

        <select id="getStudentByTeacherId" resultType="Student">
            select * from mybatis.student where tid = #{tid}
        </select>

3,小结

  1. 关联 - association 【多对一】
  2. 集合 - collection 【一对多】
  3. javaType & ofType
    1. JavaType 用来指定实体类中属性的类型
    2. ofType 用来指定映射到List或者集合中的 pojo类型,泛型中的约束类型
5,动态sql

什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

if
choose (when, otherwise)
trim (where, set)
foreach

    
    
    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog where 1=1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>

        

    <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <choose>
                <when test="title != null">
                    title = #{title}
                </when>
                <when test="author != null">
                    and author = #{author}
                </when>
                <otherwise>
                    and views = #{views}
                </otherwise>
            </choose>
        </where>
    </select>

      select * from mybatis.blog
    <where>
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </where>
    <update id="updateBlog" parameterType="map">
        update mybatis.blog
        <set>
            <if test="title != null">
                title = #{title},
            </if>
            <if test="author != null">
                author = #{author}
            </if>
        </set>
        where id = #{id}
    </update>

        
        select * from user where 1=1 and 

      <foreach item="id" collection="ids"
          open="(" separator="or" close=")">
            #{id}
      </foreach>

    (id=1 or id=2 or id=3)


        
        
        SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用!include标签引入 refid
    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>

6,缓存 MyBatis系统中默认定义了两级缓存:一级缓存二级缓存
13.3、一级缓存
  • 一级缓存也叫本地缓存: SqlSession

    • 与数据库同一次会话期间查询到的数据会放在本地缓存中。
    • 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;

  • 工作机制

    • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
    • 新的会话查询信息,就可以从二级缓存中获取内容;
    • 不同的mapper查出的数据会放在自己对应的缓存(map)中;

步骤:

  1. 开启全局缓存

    <!--显示的开启全局缓存-->
    <setting name="cacheEnabled" value="true"/>
    
  2. 在要使用二级缓存的Mapper中开启

    <!--在当前Mapper.xml中使用二级缓存-->
    <cache/>
    

    也可以自定义参数

    <!--在当前Mapper.xml中使用二级缓存-->
    <cache  eviction="FIFO"
           flushInterval="60000"
           size="512"
           readOnly="true"/>
    
  3. 测试

    1. 问题:我们需要将实体类序列化!否则就会报错!

      Caused by: java.io.NotSerializableException: com.kuang.pojo.User
      

小结:

  • 只要开启了二级缓存,在同一个Mapper下就有效
  • 所有的数据都会先放在一级缓存中;
  • 只有当会话提交,或者关闭的时候,才会提交到二级缓冲中!
posted on 2024-11-29 10:57  韩行一  阅读(17)  评论(0编辑  收藏  举报