mybatis frame sort of knowledge

mybatis frame sort of knowledge

Mybatis Framework Overview:

mybatis simple xml or annotation embodiment various configuration statement to be executed together, and through java objects ( POJOs for the final map generation sql statement execution class) and the dynamic parameter in the sql statement, the last frame is performed by mybatis and sql the results are mapped to java objects and return.

Why Mybatis:

Traditional jdbc access the database:

1. unpackaged, the original method using jdbc (loading drive, acquiring connection) operations on the database data crud

2. Create a database connection frequently, release, resulting in waste of system resources, affect system performance,

 解决:可使用数据库连接池技术

3.Sql statement belongs to the hard-coded in the code, but the practical application of sql statements often change, need to change the java code, the code is not conducive to the maintenance

 解决:将 Sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。

4. The use of hard-coded to the present prepareStatement placeholder parameter passing, because the uncertain parameters, conditions may be more or less, need to modify the code difficult to maintain.

解决:Mybatis 自动将 java 对象映射至 sql 语句,通过 statement 中的 parameterType 定义输入参数的类型。 

The presence of hard-coded analytical result set (query column name), if the change sql (parameters), cause changes in parsing code, easy maintenance system, the database record can be encapsulated as POJO class object.

解决:Mybatis 自动将 sql 执行结果映射至 java 对象,通过 statement 中的 resultType 定义输出结果的类型 

Mybatis Before Getting Started:

Environment to build:

1. Create a maven project, import-dependent coordinates. (Mybatis, mysql, log4j, junit)
2. Write the entity class Usr
3. Write persistence layer interface UserDao
4. Access to the resource directory log4j.properties
The write interface persistence layer mapping file UserDao.xml (placed in the same package persistence layer interface, consistent with the named persistence interface name)
<?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 namespace="com.itheima.dao.IUserDao">
  
<!--配置查询所有-->
<select id="findAll" resultType="com.itheima.domain.User">
    select * from user
</select>
  
</mapper>
6. Develop SqlMapConfig.xml (configuration information Mybatis operating environment, dom4j xml parsing technology)
<?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">
<!-- mybatis的主配置文件 -->
<configuration>
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息,创建连接对象 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
      <!-- 基于xml -->
        <mapper resource="com/itheima/dao/IUserDao.xml"/>
      <!-- 基于注解 -->
      <mapper class="com.itheima.dao.IUserDao.xml"/>
    </mappers>
</configuration>
7. Writing test class
public class MybatisTest {

    /**
     * 入门案例
     * @param args
     */
    public static void main(String[] args)throws Exception {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂(不是自己创建的,构建者模式)
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产SqlSession对象
        SqlSession session = factory.openSession();
        //4.使用SqlSession创建Dao接口的代理对象
        IUserDao userDao = session.getMapper(IUserDao.class);
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
        //6.释放资源
        session.close();
        in.close();
    }
}

tips:

1. Read the configuration file

First: use the class loader, class path can only read the configuration file

Second: the use of the getRealPath servletContext object ()

2. Create factory mybatis: builder mode

Advantage: the creation of hidden details of the object, so that users can directly call the method to get an object

3. Production SqlSession: Factory Pattern

Advantages: decoupling, reducing dependencies between classes. Use factory objects, resolve dependencies between classes, web development each modification changes the source, affect the development efficiency, the use of factory objects without recompiling, deployment, start the server.

4. Create Dao interface categories: proxy mode

Advantage: enhanced existing methods without modifying the source code on the basis of

Enhanced Object features:

Design Patterns: some of the ways to solve common problems fixed

1) decorative pattern

2) proxy mode

Static agent: there is a class file description proxy mode

Dynamic Agent: Agent class is formed in memory

5.prepareStament usage

tips: when executing sql statement using jdbc connection to the database (JDBC SQL statements perform many procedures produce large amounts of Statement and PreparedStatement objects.)

1. When the sql statement containing a plurality of parameters, when used multiple times, using the sql preparestament initialized mentioned precompiled database, improve efficiency;

2. You can replace variables, sql statement can contain placeholders? Put? Replaced variable, ps.setString () ....

3. Security, effectively prevent the problem of SQL injection: PreparedStatement parameters passed to the object may be forced to be cast, so that developers can ensure the match with the underlying database format when inserting or query data. (Do not understand)

to sum up:

PreparedStatement: database sql statement will be pre-compiled, the next time you perform the same sql statement, the database will simply not be pre-compiled, and the direct use of the buffer database to improve the efficiency of data access (but as far as possible to use? No way of passing parameters), if sql statement is executed only once, will no longer be reused. From the security point of view, PreparedStatement through? To pass parameters to avoid the fight sql sql injection problem occurs, so security is good.

In the development, it is recommended to use PreparedStatement

6. What is SQL injection, how to prevent SQL injection?

 The so-called SQL injection, is inserted through the SQL command into the Web form is submitted the query string or enter a domain name or page request, and ultimately to deceive the server to execute malicious SQL commands. Specifically, it is the use of existing applications, the (malicious) SQL command injection into the back-end database engine capacity of execution, it can enter the (malicious) SQL statements in a Web form to get on the site of a security vulnerability database, rather than to execute SQL statements in accordance with the designer intent.

How to prevent SQL injection, use stored procedures to execute all queries; check the legitimacy of user input; the user's login name, password and other data stored encrypted.

Mapping configuration file

crud Tags:

1.sql statement using # {} characters

As a placeholder, which is free to write the contents of a primitive type, if the parameter is an object, using the # {} in OGNL (FIG navigation target language) expression syntax is the object # {.} Objects manner

{User.username} It will first go to the user object, and then locate the object in the user attribute username and calls the getUsername () method of the value taken out. But we parameterType property specified in the entity class name, so you can omit user. The direct write username.

2.Mysql acquired id

Add records, use the insert label. Only parameters, no return value.
If you want to obtain data Mysql current record ID, you configure:
the selectKey
after operating when a method of adding, MyBatis will automatically return to the ID, to a subject set of configuration parameter object parameterType

<insert id="saveUser" parameterType="com.itheima.domain.User">
    <!-- 配置插入操作后,获取插入数据的id -->
    <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
        select last_insert_id();
    </selectKey>
    insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
</insert>
3. Fuzzy query

We did not join in the configuration file% as a condition of fuzzy query, so when passed a string argument, you need to query calibration fuzzy
knowledge%. Configuration file # {username} is just a placeholder, so the SQL statement is displayed as "?."

Another fuzzy search query: '% $ {value}%' # {} instead of

4. $ {} {} is the difference between
#{}表示一个占位符号
通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,
#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类
型值, #{}括号中可以是 value 或其它名称。
${}表示拼接 sql 串
通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简
单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值, ${}括号中只能是 value。

Mybatis depth parameters:

parameterType: Basic types and string, using the package name class name, such as Java.Lang.String.

Packaging of the fully qualified class name

Special case: the entity class and property names are inconsistent database column names, the query result is null

MySql not case-sensitive in the windows system, the mapping configuration is modified as follows:

<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user
</select>

Read:

使用别名查询
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.itheima.domain.User">
select id as userId,username as userName,birthday as userBirthday,
sex as userSex,address as userAddress from user
</select>

Question:
If a lot of our query, use aliases, then write it would not be too much trouble, there is no other solution? as follows

resultMap Result type:

<!-- 建立 User 实体和数据库表的对应关系
type 属性:指定实体类的全限定类名
id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
-->
<resultMap type="com.itheima.domain.User" id="userMap">
<id column="id" property="userId"/>
<result column="username" property="userName"/>
<result column="sex" property="userSex"/>
<result column="address" property="userAddress"/>
<result column="birthday" property="userBirthday"/>
</resultMap>
id 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称

Mapping configuration corresponding to

<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select * from user
</select>

SqlMapConfig.xml configuration updates

Label properties: jdbcConfig.properties required to extract, onto path resources

typeAliases Tags:

pakage Tags:

<!-- mybatis的主配置文件 -->
<configuration>
  
    <properties resource="jdbcConfig.properties"></properties>
  <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
       <!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
        <package name="com.itheima.domain"></package>
    </typeAliases>
  
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <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>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
       <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

Dynamic Sql statement

Dynamic SQL purpose is to better reuse fragments or flexible SQL statement generates SQL statements. In essence, that is spliced ​​SQL statement string.

if进行判断,test属性为true,就拼接上标签中的SQL语句
test中就是OGNL表达式
    1. 不要加 #{}
    2. 逻辑运算,要使用  and,or
    3. 调用对象的方法:  list.size()

    <select id="findUserByCondition" resultMap="userMap" parameterType="user">
        select * from user
        <where>
            <if test="userName != null">
                and username = #{userName}
            </if>
            <if test="userSex != null">
                and sex = #{userSex}
            </if>
        </where>
    </select>
<update id="updateUser" parameterType="user">
          update user
          <set>
              <if test="username !=null and username !=''">
                username = #{username} ,
              </if>
              <if test="username !=null">
                sex = #{sex},
              </if>
              <if test="username !=null">
              password = #{password},
              </if>
          </set>
          where id=#{id}
      </update>
foreach 进行循环的集合,必须通过包装的对象提供。
<select id="findInIds" resultType="user" parameterType="queryvo">
    <where>
      <if test="ids != null and ids.size() > 0">
          <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
          #{uid}
          </foreach>
      </if>
    </where>
</select>
将SQL中,相同的内容提取出来,在多个地方进行引用。
 1. SQL语句中的字符串
 2. 动态SQL中的标签

抽取SQL语句
    <sql id="defaultUser">
        select * from user
    </sql>
使用SQL
    <select id="findAll" resultMap="userMap">
        <include refid="defaultUser"></include>
    </select>

Sql simplified fragment

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

<!-- 配置查询所有操作 -->
<select id="findAll" resultType="user">
<include refid="defaultSql"></include>
</select>

One query

Use resultMap, the definition of special resultMap used to map one to one query results.
You can learn object-oriented (has a) relationship, we can add a User class of objects in the Account class to represent the account
which the user.

One to one mapping configuration

<resultMap id="accountUserMap" type="account">
    <id property="id" column="aid"></id>
    <result property="uid" column="uid"></result>
    <result property="money" column="money"></result>
    <!-- 一对一的关系映射:配置封装user的内容-->
    <association property="user" column="uid" javaType="user">
        <id property="id" column="id"></id>
        <result column="username" property="username"></result>
        <result column="address" property="address"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>
    </association>
</resultMap>

Many queries

<resultMap type="user" id="userMap">
<id column="id" property="id"></id>
<result column="username" property="username"/>
<result column="address" property="address"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<!-- collection 是用于建立一对多中集合属性的对应关系
ofType 用于指定集合元素的数据类型
-->
<collection property="accounts" ofType="account">
<id column="aid" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
  </collection>
</resultMap>
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
a on u.id =a.uid
</select>
</mapper>
collection
部分定义了用户关联的账户信息。表示关联查询结果集
property="accList":
关联查询的结果集存储在 User 对象的上哪个属性。
ofType="account":
指定关联查询的结果集中的对象类型即 List中的对象类型。此处可以使用别名,也可以使用全限定名。

Many to many query

<!--定义 role 表的 ResultMap-->
<resultMap id="roleMap" type="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="roleMap">
select u.*,r.id as rid,r.role_name,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id = ur.uid
</select>
</mapper>

Lazy loading

  1. What is the delay in loading, why should delay loading
    1. When the load current object to the associated object properties of an object or collection of attributes, whether the query immediately? Not immediately query is lazy loading, also known as lazy loading.
  2. How to set a delay in the loading mybatis (association, collection function includes a delay loading).
    1. In the current application, turn-on delay loading
//SqlMapConfig.xml
    <!--配置参数-->
    <settings>
        <!--开启Mybatis支持延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>  <!-- 默认就是true -->
        <setting name="aggressiveLazyLoading" value="false"></setting>
    </settings>

2. One to One

<!-- 一对一的关系映射:配置封装user的内容
        select属性指定的内容:查询用户的唯一标识:当前mapper配置的sid(namespace+id)
        column属性指定的内容:用户根据id查询时,所需要的参数的值
        -->
        <association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById"></association>

<select id="findAll" resultMap="accountMap">
select * from account
</select>
select: 填写我们要调用的 select 映射的 id
column : 填写我们要传递给 select 映射的参数

3. to-many

<!-- collection 是用于建立一对多中集合属性的对应关系
ofType 用于指定集合元素的数据类型
select 是用于指定查询账户的唯一标识(账户的 dao 全限定类名加上方法名称)
column 是用于指定使用哪个字段的值作为条件查询
-->
<collection property="accounts" ofType="account"
select="com.itheima.dao.IAccountDao.findByUid"
column="id">
</collection>


<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select * from user
</select>
<collection>标签:
主要用于加载关联的集合对象
select 属性:
用于指定查询 account 列表的 sql 语句,所以填写的是该 sql 映射的 id
column 属性:
用于指定 select 属性的 sql 语句的参数来源,上面的参数来自于 user 的 id 列,所以就写成 id 这一
个字段名了

Cache

The use of cache

  1. The role and timing of cache buffers used

    1. The cache is to reduce the interaction with the database, submission system performance
    2. Consider using this cache:
      1. Often query data, and do not often change.
      2. It allows data synchronization occurs without
  2. mybatis cache

    1. Cache

      SqlSession range of cache, with a SQLSession object, you can use the same cache. When the same data using a query session (the same method, the same parameters), the same query object.

      When the session is closed, calls the clearCache () method, CRUD operations when executed, will be cleared.

    2. Secondary cache

      SQLSessionFactory range cache generally creates only a SQLSessionFactory application objects, the current application, all the operations can be used in the secondary cache data. Different session query the same data (the same method, the same parameter) may be obtained from the secondary cache, the secondary cache to cache only the data content of each session will get different objects, have the same properties.

      Secondary cache is not enabled by default, you need to manually open.

//SqlMapConfig.xml
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

//对应的mapper文件中
<cache />

//当前配置的mapper文件的对应需要缓存的SQL上
<!-- 根据id查询用户 -->
<select id="findById" parameterType="INT" resultType="user" useCache="true">
  select * from user where id = #{uid}
</select>

Mybatis common comment

@Insert: implement new
@Update: Update achieve
@Delete: realize delete
@Select: implement the query
@Result: achieve the results set package
@Results: can be used with @Result, encapsulating multiple result sets
@ResultMap: implement referential @Results package defined
@One: package achieve one result set
@Many: result set-many packages
@SelectProvider: dynamic SQL mapping
@CacheNamespace: secondary cache implemented using annotations

  1. Setup the development environment

    If a comment develop, you can not use the xml configuration.

  2. Single table CRUD operations

  3. Object Properties Field inconsistent configuration and

    @Select("select * from user")
        @Results(id="userMap",value={
                @Result(id=true,column = "id",property = "userId"),
                @Result(column = "username",property = "userName"),
                @Result(column = "address",property = "userAddress"),
                @Result(column = "sex",property = "userSex"),
                @Result(column = "birthday",property = "userBirthday")
        })
        List<User> findAll();
      //重复使用resultmap
          @Select("select * from user  where id=#{id} ")
          @ResultMap("userMap")
          User findById(Integer userId);

    4. The object-relational mapping configuration

    1. One to One

          @Select("select * from account")
          @Results(id="accountMap",value = {
                  @Result(id=true,column = "id",property = "id"),
                  @Result(column = "uid",property = "uid"),
                  @Result(column = "money",property = "money"),
                  @Result(property = "user",column = "uid",one=@One(select="com.itheima.dao.IUserDao.findById",fetchType= FetchType.EAGER))
          })
      //property  对象属性的名称
      //column  后面配置的select查询的参数
      //one 属性是对象
        //  select 查询的方法
        //   fetchType 是否延迟加载    FetchType.EAGER 立即加载
          List<Account> findAll();

      2. many

         @Select("select * from user")
          @Results(id="userMap",value={
                  @Result(id=true,column = "id",property = "userId"),
                  @Result(column = "username",property = "userName"),
                  @Result(column = "address",property = "userAddress"),
                  @Result(column = "sex",property = "userSex"),
                  @Result(column = "birthday",property = "userBirthday"),
                  @Result(property = "accounts",column = "id",
                          many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid",
                                      fetchType = FetchType.LAZY))
          })
      // many 对象的属性是集合  fetchType = FetchType.LAZY 延迟就加载
          List<User> findAll();

Guess you like

Origin www.cnblogs.com/mll-yf/p/11355994.html