欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mybatis-Plus BaseMapper的用法詳解

 更新時(shí)間:2020年08月27日 10:48:15   作者:金色的魚兒  
這篇文章主要介紹了Mybatis-Plus BaseMapper的用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、如何使用BaseMapper進(jìn)行數(shù)據(jù)庫的操作。

2、使用BaseMapper進(jìn)行插入實(shí)體時(shí)如何讓UUID的主鍵自動(dòng)生成。

Student實(shí)體類,其中id屬性主鍵為UUID

package com.huixiaoer.ant.api.model.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;

public class Student {
  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.id
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  @TableId(type= IdType.UUID)
  private String id;

  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.user_name
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  private String userName;

  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.age
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  private Integer age;

  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.phone
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  private String phone;

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public Student(String id, String userName, Integer age, String phone) {
    this.id = id;
    this.userName = userName;
    this.age = age;
    this.phone = phone;
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public Student() {
    super();
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method returns the value of the database column student.id
   *
   * @return the value of student.id
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public String getId() {
    return id;
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method sets the value of the database column student.id
   *
   * @param id the value for student.id
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public void setId(String id) {
    this.id = id == null ? null : id.trim();
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method returns the value of the database column student.user_name
   *
   * @return the value of student.user_name
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public String getUserName() {
    return userName;
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method sets the value of the database column student.user_name
   *
   * @param userName the value for student.user_name
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public void setUserName(String userName) {
    this.userName = userName == null ? null : userName.trim();
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method returns the value of the database column student.age
   *
   * @return the value of student.age
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public Integer getAge() {
    return age;
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method sets the value of the database column student.age
   *
   * @param age the value for student.age
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public void setAge(Integer age) {
    this.age = age;
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method returns the value of the database column student.phone
   *
   * @return the value of student.phone
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public String getPhone() {
    return phone;
  }

  /**
   * This method was generated by MyBatis Generator.
   * This method sets the value of the database column student.phone
   *
   * @param phone the value for student.phone
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  public void setPhone(String phone) {
    this.phone = phone == null ? null : phone.trim();
  }
}

StudnetVI實(shí)體類,用戶從頁面接收參數(shù)

package com.huixiaoer.ant.api.model.vi;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(value = "student對象",description = "學(xué)生對象student")
public class StudentVI {


  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.user_name
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  @ApiModelProperty(value="學(xué)生姓名",name="userName",required=true)
  private String userName;

  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.age
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  @ApiModelProperty(value="年齡",name="age",required=true)
  private Integer age;

  /**
   *
   * This field was generated by MyBatis Generator.
   * This field corresponds to the database column student.phone
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  @ApiModelProperty(value="手機(jī)號",name="phone",required=true)
  private String phone;


  public String getUserName() {
    return userName;
  }

  public void setUserName(String userName) {
    this.userName = userName;
  }

  public Integer getAge() {
    return age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public String getPhone() {
    return phone;
  }

  public void setPhone(String phone) {
    this.phone = phone;
  }

}

StudentPlusMapper接口類,實(shí)現(xiàn)BaseMapper用來實(shí)現(xiàn)Mybatis-Plus的增強(qiáng)功能。

package com.huixiaoer.ant.api.repository.mysql.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.huixiaoer.ant.api.model.bean.Student;

public interface StudentPlusMapper extends BaseMapper<Student> {
  //不需要實(shí)現(xiàn),這時(shí)候就可以調(diào)用baseMapper的增刪改查了
}

StudentService業(yè)務(wù)接口類

package com.huixiaoer.ant.api.service;

import com.huixiaoer.ant.api.model.bean.Student;
import com.huixiaoer.ant.api.model.bean.StudentExample;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectKey;

import java.util.List;

public interface StudentService {
  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  long countByExample(StudentExample example);

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  int deleteByExample(StudentExample example);

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  @Insert({
    "insert into student (id, user_name, ",
    "age, phone)",
    "values (#{id,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, ",
    "#{age,jdbcType=INTEGER}, #{phone,jdbcType=VARCHAR})"
  })
  @SelectKey(statement="select uuid_short()", keyProperty="id", before=true, resultType=String.class)
  int insert(Student record);

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  int insertSelective(Student record);

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  List<Student> selectByExample(StudentExample example);

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  int updateByExampleSelective(@Param("record") Student record, @Param("example") StudentExample example);

  /**
   * This method was generated by MyBatis Generator.
   * This method corresponds to the database table student
   *
   * @mbg.generated Thu Oct 31 14:09:39 CST 2019
   */
  int updateByExample(@Param("record") Student record, @Param("example") StudentExample example);
}

StudentServiceImpl業(yè)務(wù)接口實(shí)現(xiàn)類,這里將mybatis-plus的mapper接口注入其中。

package com.huixiaoer.ant.api.service.impl;

import com.huixiaoer.ant.api.model.bean.Student;
import com.huixiaoer.ant.api.model.bean.StudentExample;
import com.huixiaoer.ant.api.repository.mysql.mapper.StudentMapper;
import com.huixiaoer.ant.api.repository.mysql.mapper.StudentPlusMapper;
import com.huixiaoer.ant.api.service.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class StudentServiceImpl implements StudentService {

  @Autowired
  private StudentMapper studentMapper;

  @Autowired
  private StudentPlusMapper studentPlusMapper;

  @Override
  public long countByExample(StudentExample example) {
    return 0;
  }

  @Override
  public int deleteByExample(StudentExample example) {
    return 0;
  }

  @Override
  public int insert(Student record) {
    return studentPlusMapper.insert(record);
  }

  @Override
  public int insertSelective(Student record) {
    return studentMapper.insertSelective(record);
  }

  @Override
  public List<Student> selectByExample(StudentExample example) {
    return null;
  }

  @Override
  public int updateByExampleSelective(Student record, StudentExample example) {
    return 0;
  }

  @Override
  public int updateByExample(Student record, StudentExample example) {
    return 0;
  }
}

SchoolController類,實(shí)現(xiàn)前端和后臺的交互。自動(dòng)注入學(xué)生業(yè)務(wù)實(shí)現(xiàn)類。

package com.huixiaoer.ant.api.controller;

import com.huixiaoer.ant.api.common.constant.ResultCode;
import com.huixiaoer.ant.api.model.bean.Student;
import com.huixiaoer.ant.api.model.vi.StudentVI;
import com.huixiaoer.ant.api.service.impl.StudentServiceImpl;
import com.huixiaoer.ant.api.util.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @author create by yiqiang.wu
 * @create 2019/06/12
 * @email yiqiang.wu@huixiaoer.com
 * @description 登錄
 */
@Slf4j
@RestController
@Api(tags = "學(xué)校 相關(guān)接口")
public class SchoolController {

  @Autowired
  private StudentServiceImpl studentService;

  @Autowired
  private HttpServletRequest request;

  @ApiOperation(value = "增加學(xué)生信息")
  @PostMapping(value = "/insert/student")
  public CommonResult insertStudent(@RequestBody @ApiParam(name="學(xué)生對象",value="傳入json格式",required=true) StudentVI studentVI) {
    try {
      Student student = new Student();
//      student.setId(UUID.randomUUID().toString());
      student.setUserName(studentVI.getUserName());
      student.setAge(studentVI.getAge());
      student.setPhone(studentVI.getPhone());
      studentService.insert(student);
    } catch (Exception e) {
      System.out.println(e);
      return CommonUtil.buildResponse(ResultCode.SYSTEM_ERROR, ResultCode.SYSTEM_ERROR_MSG);
    }
    return CommonUtil.buildResponse(ResultCode.SUCCESS, ResultCode.SUCCESS_MSG);
  }

}

補(bǔ)充一下Mybatis的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.huixiaoer.ant.api.repository.mysql.mapper.StudentMapper">
 <resultMap id="BaseResultMap" type="com.huixiaoer.ant.api.model.bean.Student">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  <constructor>
   <arg column="id" javaType="java.lang.String" jdbcType="VARCHAR" />
   <arg column="user_name" javaType="java.lang.String" jdbcType="VARCHAR" />
   <arg column="age" javaType="java.lang.Integer" jdbcType="INTEGER" />
   <arg column="phone" javaType="java.lang.String" jdbcType="VARCHAR" />
  </constructor>
 </resultMap>
 <sql id="Example_Where_Clause">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  <where>
   <foreach collection="oredCriteria" item="criteria" separator="or">
    <if test="criteria.valid">
     <trim prefix="(" prefixOverrides="and" suffix=")">
      <foreach collection="criteria.criteria" item="criterion">
       <choose>
        <when test="criterion.noValue">
         and ${criterion.condition}
        </when>
        <when test="criterion.singleValue">
         and ${criterion.condition} #{criterion.value}
        </when>
        <when test="criterion.betweenValue">
         and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
        </when>
        <when test="criterion.listValue">
         and ${criterion.condition}
         <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
          #{listItem}
         </foreach>
        </when>
       </choose>
      </foreach>
     </trim>
    </if>
   </foreach>
  </where>
 </sql>
 <sql id="Update_By_Example_Where_Clause">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  <where>
   <foreach collection="example.oredCriteria" item="criteria" separator="or">
    <if test="criteria.valid">
     <trim prefix="(" prefixOverrides="and" suffix=")">
      <foreach collection="criteria.criteria" item="criterion">
       <choose>
        <when test="criterion.noValue">
         and ${criterion.condition}
        </when>
        <when test="criterion.singleValue">
         and ${criterion.condition} #{criterion.value}
        </when>
        <when test="criterion.betweenValue">
         and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
        </when>
        <when test="criterion.listValue">
         and ${criterion.condition}
         <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
          #{listItem}
         </foreach>
        </when>
       </choose>
      </foreach>
     </trim>
    </if>
   </foreach>
  </where>
 </sql>
 <sql id="Base_Column_List">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  id, user_name, age, phone
 </sql>
 <select id="selectByExample" parameterType="com.huixiaoer.ant.api.model.bean.StudentExample" resultMap="BaseResultMap">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  select
  <if test="distinct">
   distinct
  </if>
  <include refid="Base_Column_List" />
  from student
  <if test="_parameter != null">
   <include refid="Example_Where_Clause" />
  </if>
  <if test="orderByClause != null">
   order by ${orderByClause}
  </if>
 </select>
 <delete id="deleteByExample" parameterType="com.huixiaoer.ant.api.model.bean.StudentExample">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  delete from student
  <if test="_parameter != null">
   <include refid="Example_Where_Clause" />
  </if>
 </delete>
 <insert id="insertSelective" parameterType="com.huixiaoer.ant.api.model.bean.Student">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
   select uuid_short()
  </selectKey>
  insert into student
  <trim prefix="(" suffix=")" suffixOverrides=",">
   id,
   <if test="userName != null">
    user_name,
   </if>
   <if test="age != null">
    age,
   </if>
   <if test="phone != null">
    phone,
   </if>
  </trim>
  <trim prefix="values (" suffix=")" suffixOverrides=",">
   #{id,jdbcType=VARCHAR},
   <if test="userName != null">
    #{userName,jdbcType=VARCHAR},
   </if>
   <if test="age != null">
    #{age,jdbcType=INTEGER},
   </if>
   <if test="phone != null">
    #{phone,jdbcType=VARCHAR},
   </if>
  </trim>
 </insert>
 <select id="countByExample" parameterType="com.huixiaoer.ant.api.model.bean.StudentExample" resultType="java.lang.Long">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  select count(*) from student
  <if test="_parameter != null">
   <include refid="Example_Where_Clause" />
  </if>
 </select>
 <update id="updateByExampleSelective" parameterType="map">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  update student
  <set>
   <if test="record.id != null">
    id = #{record.id,jdbcType=VARCHAR},
   </if>
   <if test="record.userName != null">
    user_name = #{record.userName,jdbcType=VARCHAR},
   </if>
   <if test="record.age != null">
    age = #{record.age,jdbcType=INTEGER},
   </if>
   <if test="record.phone != null">
    phone = #{record.phone,jdbcType=VARCHAR},
   </if>
  </set>
  <if test="_parameter != null">
   <include refid="Update_By_Example_Where_Clause" />
  </if>
 </update>
 <update id="updateByExample" parameterType="map">
  <!--
   WARNING - @mbg.generated
   This element is automatically generated by MyBatis Generator, do not modify.
   This element was generated on Thu Oct 31 14:09:39 CST 2019.
  -->
  update student
  set id = #{record.id,jdbcType=VARCHAR},
   user_name = #{record.userName,jdbcType=VARCHAR},
   age = #{record.age,jdbcType=INTEGER},
   phone = #{record.phone,jdbcType=VARCHAR}
  <if test="_parameter != null">
   <include refid="Update_By_Example_Where_Clause" />
  </if>
 </update>
</mapper>

各種UUID生成策略,生成的UUID值進(jìn)行比較。

到此這篇關(guān)于Mybatis-Plus BaseMapper的用法詳解的文章就介紹到這了,更多相關(guān)Mybatis-Plus BaseMapper內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot 使用 maven-resources-plugin 打包變量替換jar沒有打包進(jìn)去、Jar包沒有被使用的解決方法

    Springboot 使用 maven-resources-plugin 打包變量替換ja

    這篇文章主要介紹了Springboot 使用 maven-resources-plugin 打包變量替換jar沒有打包進(jìn)去、Jar包沒有被使用的解決方法,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2024-08-08
  • idea插件無法下載4的種解決方式

    idea插件無法下載4的種解決方式

    這篇文章主要介紹了idea插件無法下載4的種解決方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Java程序單實(shí)例運(yùn)行的簡單實(shí)現(xiàn)

    Java程序單實(shí)例運(yùn)行的簡單實(shí)現(xiàn)

    這篇文章主要介紹了Java程序單實(shí)例運(yùn)行的簡單實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • mybatis 如何判斷l(xiāng)ist集合是否包含指定數(shù)據(jù)

    mybatis 如何判斷l(xiāng)ist集合是否包含指定數(shù)據(jù)

    這篇文章主要介紹了mybatis 判斷l(xiāng)ist集合是否包含指定數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • java 中@Deprecated 注解的實(shí)例詳解

    java 中@Deprecated 注解的實(shí)例詳解

    這篇文章主要介紹了java 中@Deprecated 注解的實(shí)例詳解的相關(guān)資料,這里對@Deprecated注解進(jìn)行了詳細(xì)介紹,希望能幫助到大家,需要的朋友可以參考下
    2017-08-08
  • 淺談Java動(dòng)態(tài)代理的實(shí)現(xiàn)

    淺談Java動(dòng)態(tài)代理的實(shí)現(xiàn)

    最近,小組同事做代碼改造時(shí),使用到了動(dòng)態(tài)代理,自己閱讀時(shí),發(fā)現(xiàn)對代理這種設(shè)計(jì)模式都不怎么清楚,導(dǎo)致理解代碼也很困難 自己唯一能看懂的,大概就是handler中的invoke方法 ,文中作出了非常詳細(xì)的介紹,需要的朋友可以參考下
    2021-05-05
  • 一文詳解Java中的反射與new創(chuàng)建對象

    一文詳解Java中的反射與new創(chuàng)建對象

    Java中的反射(Reflection)和使用new關(guān)鍵字創(chuàng)建對象是兩種不同的對象創(chuàng)建方式,各有優(yōu)缺點(diǎn)和適用場景,本文小編給大家詳細(xì)介紹了Java中的反射與new創(chuàng)建對象,感興趣的小伙伴跟著小編一起來看看吧
    2024-07-07
  • 基于JavaBean編輯器讀取peroperties文件的實(shí)例

    基于JavaBean編輯器讀取peroperties文件的實(shí)例

    下面小編就為大家?guī)硪黄贘avaBean編輯器讀取peroperties文件的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • Java微信公眾平臺開發(fā)(2) 微信服務(wù)器post消息體的接收

    Java微信公眾平臺開發(fā)(2) 微信服務(wù)器post消息體的接收

    這篇文章主要為大家詳細(xì)介紹了Java微信公眾平臺開發(fā)第二步,微信服務(wù)器post消息體的接收,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Spring Boot集成教程之異步調(diào)用Async

    Spring Boot集成教程之異步調(diào)用Async

    在項(xiàng)目中,當(dāng)訪問其他人的接口較慢或者做耗時(shí)任務(wù)時(shí),不想程序一直卡在耗時(shí)任務(wù)上,想程序能夠并行執(zhí)行,我們可以使用多線程來并行的處理任務(wù),也可以使用spring提供的異步處理方式@Async。需要的朋友們下面來一起看看吧。
    2018-03-03

最新評論