



  

<!DOCTYPE html>
<html
  lang="en"
  
  data-color-mode="auto" data-light-theme="light" data-dark-theme="dark"
  data-a11y-animated-images="system" data-a11y-link-underlines="true"
  
  >




  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">

<script type="importmap">{"imports":{"react":"https://github.githubassets.com/assets/react-e27d1b3e03961e68.js","react-dom":"https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js","react-dom/client":"https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js","react-is":"https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js","react-reconciler":"https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js","react/compiler-runtime":"https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js","react/jsx-dev-runtime":"https://github.githubassets.com/assets/react-jsx-dev-runtime-ea55d68667d559e5.js","react/jsx-runtime":"https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js","scheduler":"https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js"}}</script>
<meta name="react-profiling" content="0" data-turbo-transient="true" />
<meta name="react-import-map" content="react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@777f63f87cd0" data-turbo-track="reload" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-e27d1b3e03961e68.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js" />

  


  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-99f877e9ddfc0e51.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light_high_contrast-48fdd0811afbab3c.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-79ad2ace604703b3.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark_high_contrast-24484a076f02295f.css" /><link data-color-theme="light" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light-99f877e9ddfc0e51.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-48fdd0811afbab3c.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-f4bf1142976e4bbf.css" /><link data-color-theme="light_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind_high_contrast-f661b49995ba0bd8.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-0b38d22346321c92.css" /><link data-color-theme="light_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia_high_contrast-f1c62c9e70259b9f.css" /><link data-color-theme="dark" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark-79ad2ace604703b3.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-24484a076f02295f.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-f50cacf0a86b9929.css" /><link data-color-theme="dark_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind_high_contrast-e61d4f4ca17852c2.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-39c10993d5603fac.css" /><link data-color-theme="dark_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia_high_contrast-73236c840c0c7d90.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-0de76f07cc035b10.css" /><link data-color-theme="dark_dimmed_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed_high_contrast-fd1500c8744e40d6.css" />

  <style type="text/css">
    :root {
      --tab-size-preference: 4;
    }

    pre, code {
      tab-size: var(--tab-size-preference);
    }
  </style>

    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-ed9ca172356fd545.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-1d2c7f7b52a6068b.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-54ba76e934a49d7c.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-456bd5deb85c7ecd.css" />
  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-11ee8a031c040c1a.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-2d56bdb0166c0238.css" />

  

  <script type="application/json" id="client-env">{"locale":"en","featureFlags":["actions_enable_background_steps","actions_new_hosted_runner_image_select_sizes_and_versions","activity_diff_file_tree","activity_repos_file_tree","activity_repos_overview_header","activity_repos_overview_sidebar","agent_author_search_expansion","agent_author_search_expansion_ui_pulls","alternate_user_config_repo","async_conversion_coverage_enabled","billing_billable_licenses_cost_center_bucket_fix","billing_budget_expiration","billing_cost_center_list_assigned_resources","billing_discount_threshold_notification","code_quality_enablement_banner_targeting","code_quality_remove_preview","code_view_raf_sticky_lines","codespaces_prebuild_region_target_update","coding_agent_third_party_model_ui","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_automation_repo_mcp_servers","copilot_automations_pagination","copilot_chat_auto_mode_v2","copilot_chat_clear_model_selection_for_default_change","copilot_chat_header_reorder","copilot_chat_max_upsell","copilot_chat_models_browser_cache","copilot_chat_vision_dotcom_chat_ga_gate","copilot_css_textarea_autosize","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_removal_on_marketplace","copilot_fix_failed_workflows_all_skus","copilot_hide_hovercard","copilot_immersive_embedded_header_button","copilot_immersive_file_preview_keep_mounted","copilot_immersive_task_hyperlinking","copilot_mc_cli_resume_any_users_task","copilot_mission_control_agent_merge_fix_ci","copilot_mission_control_agent_merge_resolve_conflicts","copilot_mission_control_early_stop","copilot_mission_control_environment_list_icons","copilot_mission_control_managed_sandbox_environments","copilot_mission_control_needs_attention","copilot_mission_control_reasoning_effort","copilot_mission_control_sandbox_client_side_clone","copilot_mission_control_sandbox_remote_bypass","copilot_mission_control_session_filters","copilot_mission_control_task_alive_updates","copilot_mission_control_task_sharing","copilot_org_policy_page_focus_mode","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_authorization_status_ui","copilot_swe_agent_automation_resource_scoped_writes","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_issue_comment_trigger","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_pull_request_comment_trigger","copilot_swe_agent_pull_request_merged_trigger","copilot_swe_agent_pull_request_opened_trigger","copilot_swe_agent_pull_request_synchronize_trigger","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_task_scoped_alive_channel","copilot_token_based_billing","copilot_unconfigured_is_inherited","copilot_user_can_upgrade_plan_field","copilot_workbench_sunset","copilot_workbench_sunset_redirect","copilot_workbench_ubb","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","glc_code_quality_repo_settings_workflow_config","hide_github_models_ui","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","in_product_messaging_datadog_monitoring","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","ipm_ubb_individual_budget_banner","issue_fields_multi_select","issue_inline_avatars","issue_pinned_views","issue_pinned_views_optimistic_updates","issue_relative_time_micro","issues_dashboard_sso_structured_errors","issues_expanded_file_types","issues_hide_closed_sub_issues","issues_lazy_load_comment_box_suggestions","issues_optimistic_linked_branch_create","issues_react_chrome_container_query_fix","labels_archiving","labels_archiving_info","landing_pages_ninetailed","lifecycle_label_name_updates","marketing_cookie_consent_banner","marketing_pages_search_explore_provider","memex_client_env_github_domain","memex_default_issue_create_repository","memex_lazy_hydrate_agent_tasks","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_queue_restricted_pushers_warning","merge_status_checks_refetch_dedupe","merge_status_header_feedback","oauth_authorize_clickjacking_protection","octocaptcha_origin_optimization","primer_react_css_anchor_positioning","primer_react_merged_forwarded_refs","prs_copilot_app_open_action","prs_css_anchor_positioning","pull_request_commit_checks_dialog","pull_request_copilot_attribution_header","pull_request_overview_panel_edit_description","pull_request_persister","pull_request_stacks_feedback_dialog","pull_request_virtualization_image_estimate","pull_request_virtualization_scroll_compensation","pull_request_virtualization_scroll_intent","quick_search_lazy_suggestions","react_blob_isolate_code_lines","react_blob_ssr_content_visibility","react_data_router_tanstack_allowed","react_query_props_with_key","react_sandbox_future_tanstack","repo_app_turbo","repo_issues_sidebar_layout","repo_pulls_dashboard_persistence","repo_pulls_dashboard_sidebar_links","repos_contributors_limited_default_range","review_involves_filter","rule_ignored_file_paths","rulesets_actor_list_editor","sample_network_conn_type","security_center_artifact_filters_popover","see_who_reacted","semantic_similarity_duplicate_issue_detection","session_logs_ungroup_reasoning_text","set_sha256_on_repo_creation_form","site_banner_desktop_copilot_app","site_ghca_pixel_mona","site_github_app_ga_page","site_github_app_ga_page_highlight","site_github_app_mobile_native_share","site_global_banner_dev_days_attendee","site_global_banner_learn_copilot_sdk","site_global_nav_spark_models_removed","spark_prompt_secret_scanning","spark_server_connection_status","suggest_custom_property_values_copilot","suppress_automated_browser_vitals","swp_forms_disable_octocaptcha","thread_resolution_reason","ui_service_compute_proxy_control","ui_service_referrer_metrics","ui_service_staleness_detection","update_issue_suggestions","user_code_paste_ux","viewscreen_sandbox","warn_inaccessible_attachments","webp_support","workbench_store_readonly","workstream_plugin_bootstrap"],"githubDomain":"https://github.com","copilotApiOverrideUrl":"https://api.githubcopilot.com","cmcApiUrl":"https://api.github.com/cmc_internal/api"}</script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/high-contrast-cookie-e3d808ee18eb9784.js"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-runtime-89a2d3d9acbbacfc.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-foundation-74e9766bd696d26a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-runtime-ecf766ea8a2c7fd6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fetch-utilities-8e3d9c5d57d50312.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ser-cd1b421ad0ad7ed5.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/environment-a56a70a0e37d3cd9.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-runtime.b6099d51b9e67b57.module.css" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/catalyst-86a8f5de995615f8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/selector-observer-e88088f989b27670.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/relative-time-element-7cdf4e0db98b997c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/by-6b3c07383371bf58.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ja9-36f036c13c2e3a4c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/kw-866fd9513ae95106.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r1-b075aab3204f32f9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jz5-7c5d1669717041f8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hj-5126390ff433704d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j05-dce4d588268f0f7e.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/github-elements-5257caf8b5e4661d.js" defer="defer"></script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/element-registry-2ccf60baf44e4355.js" defer="defer"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/runtime-helpers-f3f5d71440009c48.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/aria-live-76b18916d0c8ec4d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hotkey-5109c77d7ac61078.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-core-fbb00aaa3ab9abdf.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/04n-51c49ba758739f13.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ur-024971cb63acad59.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4t-364e19c63d726e9a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/6ny-c969fbae697a356f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/yhq-3a209035a30b1a09.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/z1v-da5b33b877bfa358.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wo-09f85d22a6c8931b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/9y-81cfe57dc9040f3e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j0-41a4cf04cbd99503.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/0p-81491ed0d9d666e2.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/behaviors-1755073bea650472.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.5858534b1c27f133.module.css" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-menu-322800398a654253.js" defer="defer"></script>
  
  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/primer-react-12ebdc24dcff1ecc.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ncx-9a860680a5f230b9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j6-363f0ebf4f62f310.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t7l-bf6f21d7e7a43c35.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fe-7576d9b281e2106a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wsr-5fd3071e5a9061ab.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/0n-ecadb2ffe6b01ba2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xv-51cb34754bda73a9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/n4u-6317ce1c31aed1db.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j8s-d90ce3a169b741ed.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/la-de176c4ee471f2b3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/eag-d9eea130fa716df9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y2-87df441f1bc5a264.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/kcz-607e36c8a3751cf0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/x4-65dba777efd828f3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/gzu-1a09248f686325f6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/bi0-e2f78de823e39ca9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/on-95be29ba1ef725d9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/b1-1dbc371cef78c3c1.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/0l5-c4edb8ab48c5846d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/c2z-c92998400310b94b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/f9-038758dcbfe08dab.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/0k-b7df0a74912a42bf.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sp-915c6643cc0d7d44.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/og-93ae8b358505d372.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/b9-69d9b60a1b1fcd59.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ec-8ea7978d3fcd114e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/du-a401e69a37d95bcc.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ql0-1c18210f6b9e2263.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/20-0a2e46387735f1f4.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/dsj-cb1e4ddbce4f007b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-9f5235d335ab624b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ko6-9e80f7ac359e3c43.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/uw-8c275f7ac25b7cf6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/bsb-4f4ac8c20da73fac.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/w5-13e3a7548bb20af9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fm-c00a7677663ba326.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/z-45022d3da7b8817e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/h0-010921512138e12f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5p-ae5db0820116fb43.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/8vq-b2af216e992e11ef.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/g5-88f2a4514daa19ca.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xc-f5d51b571cd317cb.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/arw-51e8918a1b75a80f.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-view-98494470d6f5ad9e.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.9d59d1018a52a53c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/ql0.de7a55ca73db5693.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/z.812a998e1961b84d.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/xc.13e027137438fd9f.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.d94223c1464c7ec0.module.css" />

  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hu-1fc0b2a167afc025.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fb-ef2c91536abed646.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/notifications-subscriptions-menu-b63997e1d55ff582.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.9d59d1018a52a53c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/notifications-subscriptions-menu.d166fa2536e16312.module.css" />


  <title>springboot-guide/docs/MyBatisPlus.md at master · CodingDocs/springboot-guide · GitHub</title>



  <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient>
  <meta name="route-controller" content="blob" data-turbo-transient>
  <meta name="route-action" content="show" data-turbo-transient>
  <meta name="fetch-nonce" content="v2:ea928cef-2d47-0804-a12d-fa67febf7a22">

    
  <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb">


  <meta name="request-id" content="CB6E:2D7A83:115DFFFB:102A1ACD:6AAC89A2" data-pjax-transient="true"/><meta name="html-safe-nonce" content="e601371fb88560b4fb702001a8e7876b36e2cc7378ce978395dd75a54a2417b9" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDQjZFOjJEN0E4MzoxMTVERkZGQjoxMDJBMUFDRDo2QUFDODlBMiIsInZpc2l0b3JfaWQiOiI0NTYwNjU5ODg0NTk1MjUxNjE4IiwicmVnaW9uX2VkZ2UiOiJmcmEiLCJyZWdpb25fcmVuZGVyIjoiZnJhIn0=" data-pjax-transient="true"/><meta name="visitor-hmac" content="8d6c11758ae1bf97e715144607db5a382c76bd01563b88b704184037eaf00b16" data-pjax-transient="true"/>


    <meta name="hovercard-subject-tag" content="repository:159422409" data-turbo-transient>


  <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" />
  

  <meta name="selected-link" value="repo_source" data-turbo-transient>
  <link rel="assets" href="https://github.githubassets.com/">

    <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I">

<meta name="octolytics-url" content="https://collector.github.com/github/collect" />





  <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-turbo-transient="true" />

  




    <meta name="user-login" content="">

  

    <meta name="viewport" content="width=device-width">

    

      <meta name="description" content="SpringBoot2.0+从入门到实战！. Contribute to CodingDocs/springboot-guide development by creating an account on GitHub.">

      <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">

    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
    <meta property="fb:app_id" content="1401488693436528">
    <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md" />

      <meta name="twitter:image" content="https://opengraph.githubassets.com/70854a28bcc46758266a908a21f501e07a338eb2e2c3828ef6ba534fc41f3e3a/CodingDocs/springboot-guide" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="springboot-guide/docs/MyBatisPlus.md at master · CodingDocs/springboot-guide" /><meta name="twitter:description" content="SpringBoot2.0+从入门到实战！. Contribute to CodingDocs/springboot-guide development by creating an account on GitHub." />
  <meta property="og:image" content="https://opengraph.githubassets.com/70854a28bcc46758266a908a21f501e07a338eb2e2c3828ef6ba534fc41f3e3a/CodingDocs/springboot-guide" /><meta property="og:image:alt" content="SpringBoot2.0+从入门到实战！. Contribute to CodingDocs/springboot-guide development by creating an account on GitHub." /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="springboot-guide/docs/MyBatisPlus.md at master · CodingDocs/springboot-guide" /><meta property="og:url" content="https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md" /><meta property="og:description" content="SpringBoot2.0+从入门到实战！. Contribute to CodingDocs/springboot-guide development by creating an account on GitHub." />
  




      <meta name="hostname" content="github.com">



        <meta name="expected-hostname" content="github.com">


  <meta http-equiv="x-pjax-version" content="06a4674ee24562ea5052496fc3e70138222f300d538c8ed11ed662e06d8cc35f" data-turbo-track="reload">
  <meta http-equiv="x-pjax-csp-version" content="0c5c6e5334a905d8f9521e09eadcffba484d422e0d262e07ff922e6bc18b2ac6" data-turbo-track="reload">
  <meta http-equiv="x-pjax-css-version" content="ec4c7b86d7b57240253150b827ea48b04e08d8760dc6553d2a04f62000f3fe0c" data-turbo-track="reload">
  <meta http-equiv="x-pjax-js-version" content="5d46ab775ab45f2469c16543c4576d165d4daf688f9e0d2dad80844c9140daea" data-turbo-track="reload">

  <meta name="turbo-cache-control" content="no-preview" data-turbo-transient="">

      <meta name="turbo-cache-control" content="no-cache" data-turbo-transient>

    <meta data-hydrostats="publish">

  <meta name="go-import" content="github.com/CodingDocs/springboot-guide git https://github.com/CodingDocs/springboot-guide.git">

  <meta name="octolytics-dimension-user_id" content="80885507" /><meta name="octolytics-dimension-user_login" content="CodingDocs" /><meta name="octolytics-dimension-repository_id" content="159422409" /><meta name="octolytics-dimension-repository_nwo" content="CodingDocs/springboot-guide" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="159422409" /><meta name="octolytics-dimension-repository_network_root_nwo" content="CodingDocs/springboot-guide" />
  



    

    <meta name="turbo-body-classes" content="logged-out env-production page-responsive">
  <meta name="disable-turbo" content="false">


  <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">


  <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">

  <meta name="release" content="3cd165380c357735b85d5d59b7534de750eabde3" data-turbo-track="reload">
  <meta name="ui-target" content="full">

  <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000">
  <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png">
  <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon">

<meta name="theme-color" content="#1e2327">
<meta name="color-scheme" content="light dark" />


  <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">

  </head>

  <body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
    <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
      <div id="__primerPortalRoot__" style="z-index: 1000; position: absolute; width: 100%;" data-turbo-permanent></div>
      

    <div class="position-relative header-wrapper js-header-wrapper ">
      <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 tmp-py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a>

      <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full">
    <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span>
</span>      
      <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/l7j-2ddd8b435dadae28.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-37a0a10de76f6bbc.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.9d59d1018a52a53c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.7461822a900837b9.module.css" />

<react-partial
  partial-name="keyboard-shortcuts-dialog"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>





      

          
          

                <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2l-8671acba87bc0dcb.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/i26-f2ae65b837c90ae7.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fz5-23f28c0f388769c9.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/lht-26506ea833dda5be.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p1-76a75a6081059b19.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3d-82c347d20a13fb90.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tua-c4ca62c5e0e0318e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4s-c22d880230690e1f.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/marketing-header-775584f684178974.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.9d59d1018a52a53c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-brand-css.6a01c236ff527e7e.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/4s.e3d02f110161be52.module.css" />

<react-partial
  partial-name="marketing-header"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"color_mode":"dark","logged_in":false,"marketing_page":false,"home_path":"/","login_path":"/login?return_to=https%3A%2F%2Fgithub.com%2FCodingDocs%2Fspringboot-guide%2Fblob%2Fmaster%2Fdocs%2FMyBatisPlus.md","signup_path":"/signup?ref_cta=Sign+up\u0026ref_loc=header+logged+out\u0026ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow\u0026source=header-repo\u0026source_repo=CodingDocs%2Fspringboot-guide","signup_enabled":true,"is_signup_controller":false,"show_search_and_nav":true,"hide_search":false,"private_mode_enabled":false,"should_use_dotcom_links":true,"auth_hydro_click":"{\"event_type\":\"authentication.click\",\"payload\":{\"location_in_page\":\"site header menu\",\"repository_id\":null,\"auth_type\":\"SIGN_UP\",\"originating_url\":\"https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md\",\"user_id\":null}}","auth_hydro_click_hmac":"e68cad6441adef570167d364ec2fcc10b746def6fb84e42c2fdceeef934d01cd","overlay":false,"fixed":false}}</script>
  <div data-target="react-partial.reactRoot"><div data-color-mode="dark" data-light-theme="light" data-dark-theme="dark"><header class="MarketingHeader-module__root__Tk7n3 HeaderMktg header-logged-out" role="banner" data-marketing-header="true" data-color-mode="dark" data-light-theme="light" data-dark-theme="dark" data-is-top="true"><h2 class="MarketingHeader-module__visuallyHidden__sqKsl">Navigation Menu</h2><button type="button" class="MarketingHeader-module__backdrop__sw4RU" aria-label="Close navigation menu"></button><div class="MarketingHeader-module__bar__mBSyE"><div class="MarketingHeader-module__topRow__yeury"><div class="MarketingHeader-module__toggleSlot__hDxbh"><button type="button" class="HeaderMenuToggle-module__toggle__i8EiC" aria-label="Toggle navigation" aria-expanded="false"><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span></button></div><a href="/" aria-label="Homepage" class="HeaderLogo-module__logo__UFyHI" data-analytics-event="{&quot;action&quot;:&quot;homepage&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;logo&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;homepage_link_logo_header&quot;}"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github" viewBox="0 0 24 24" width="32" height="32" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path></svg></a><div class="AuthCTAs-module__mobileActions__NNzeV"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/login?return_to=https%3A%2F%2Fgithub.com%2FCodingDocs%2Fspringboot-guide%2Fblob%2Fmaster%2Fdocs%2FMyBatisPlus.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e68cad6441adef570167d364ec2fcc10b746def6fb84e42c2fdceeef934d01cd"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_3dd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_3dd_">Appearance settings</div></div></div><div class="MarketingHeader-module__menu__GIy3y"><div class="MarketingHeader-module__menuWrapper__owstH"><nav class="MarketingNavigation-module__nav__W0KYY" aria-label="Global"><ul class="MarketingNavigation-module__list__tFbMb"><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_nd_">Platform<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5knd_">AI CODE CREATION</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot" data-analytics-event="{&quot;action&quot;:&quot;github_copilot&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>GitHub Copilot</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Write better code with AI</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/ai/github-app" data-analytics-event="{&quot;action&quot;:&quot;github_copilot_app&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_app_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656"></path></svg>GitHub Copilot app</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Direct agents from issue to merge</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/mcp" data-analytics-event="{&quot;action&quot;:&quot;mcp_registry&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;mcp_registry_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mcp NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.52 1.12a3.578 3.578 0 0 1 6.078 2.98 3.578 3.578 0 0 1 2.982 6.08l-3.292 3.293a.252.252 0 0 0 0 .354l.843.843a.749.749 0 1 1-1.06 1.06l-.844-.843a1.75 1.75 0 0 1 0-2.474L13.52 9.12a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0L7.731 9.03A.75.75 0 0 1 6.67 7.97l2.85-2.85a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0l-4.799 4.8A.75.75 0 0 1 .72 5.92Z"></path><path d="M7.52 3.12a.749.749 0 1 1 1.06 1.06L5.731 7.03A2.079 2.079 0 0 0 8.67 9.97l2.85-2.85a.749.749 0 1 1 1.06 1.06l-2.849 2.85A3.578 3.578 0 0 1 4.67 5.97Z"></path></svg>MCP Registry</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Integrate external tools</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9knd_">DEVELOPER WORKFLOWS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/actions" data-analytics-event="{&quot;action&quot;:&quot;actions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;actions_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-workflow NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path></svg>Actions</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Automate any workflow</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/codespaces" data-analytics-event="{&quot;action&quot;:&quot;codespaces&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;codespaces_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codespaces NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path></svg>Codespaces</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Instant dev environments</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/issues" data-analytics-event="{&quot;action&quot;:&quot;issues&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;issues_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg>Issues</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Plan and track work</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-review" data-analytics-event="{&quot;action&quot;:&quot;code_review&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_review_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg>Code Review</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Manage code changes</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-quality" data-analytics-event="{&quot;action&quot;:&quot;code_quality&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_quality_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codescan-checkmark NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.28 6.28a.75.75 0 1 0-1.06-1.06L6.25 8.19l-.97-.97a.75.75 0 0 0-1.06 1.06l1.5 1.5a.75.75 0 0 0 1.06 0l3.5-3.5Z"></path><path d="M7.5 15a7.5 7.5 0 1 1 5.807-2.754l2.473 2.474a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2.474-2.473A7.472 7.472 0 0 1 7.5 15Zm0-13.5a6 6 0 1 0 4.094 10.386.748.748 0 0 1 .293-.292 6.002 6.002 0 0 0 1.117-6.486A6.002 6.002 0 0 0 7.5 1.5Z"></path></svg>Code Quality</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enforce quality at merge</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dknd_">APPLICATION SECURITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Find and fix vulnerabilities</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/code-security" data-analytics-event="{&quot;action&quot;:&quot;code_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code-square NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>Code security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Secure your code as you build</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/secret-protection" data-analytics-event="{&quot;action&quot;:&quot;secret_protection&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;secret_protection_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-lock NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M4 4a4 4 0 0 1 8 0v2h.25c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 12.25 15h-8.5A1.75 1.75 0 0 1 2 13.25v-5.5C2 6.784 2.784 6 3.75 6H4Zm8.25 3.5h-8.5a.25.25 0 0 0-.25.25v5.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25ZM10.5 6V4a2.5 2.5 0 1 0-5 0v2Z"></path></svg>Secret protection</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Stop leaks before they start</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ NavGroup-module__hasSeparator__FnMrN"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_hknd_">EXPLORE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_hknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/why-github" data-analytics-event="{&quot;action&quot;:&quot;why_github&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;why_github_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Why GitHub</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog" data-analytics-event="{&quot;action&quot;:&quot;blog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;blog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Blog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog/changelog" data-analytics-event="{&quot;action&quot;:&quot;changelog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;changelog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Changelog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/marketplace" data-analytics-event="{&quot;action&quot;:&quot;marketplace&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;marketplace_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Marketplace</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/features" data-analytics-event="{&quot;action&quot;:&quot;view_all_features&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_features_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all features</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_17d_">Solutions<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_17d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5l7d_">BY COMPANY SIZE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprises&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Enterprises</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/team" data-analytics-event="{&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Small and medium teams</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise/startups" data-analytics-event="{&quot;action&quot;:&quot;startups&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Startups</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/nonprofits" data-analytics-event="{&quot;action&quot;:&quot;nonprofits&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Nonprofits</span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9l7d_">BY USE CASE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/app-modernization" data-analytics-event="{&quot;action&quot;:&quot;app_modernization&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;app_modernization_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">App Modernization</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devsecops" data-analytics-event="{&quot;action&quot;:&quot;devsecops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevSecOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/ci-cd" data-analytics-event="{&quot;action&quot;:&quot;ci/cd&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ci/cd_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">CI/CD</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/use-case" data-analytics-event="{&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all use cases</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dl7d_">BY INDUSTRY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dl7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/healthcare" data-analytics-event="{&quot;action&quot;:&quot;healthcare&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Healthcare</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/financial-services" data-analytics-event="{&quot;action&quot;:&quot;financial_services&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Financial services</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/manufacturing" data-analytics-event="{&quot;action&quot;:&quot;manufacturing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Manufacturing</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/government" data-analytics-event="{&quot;action&quot;:&quot;government&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Government</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/industry" data-analytics-event="{&quot;action&quot;:&quot;view_all_industries&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all industries</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions" data-analytics-event="{&quot;action&quot;:&quot;view_all_solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_solutions_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all solutions</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_1nd_">Resources<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_1nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5lnd_">EXPLORE BY TOPIC</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=ai" data-analytics-event="{&quot;action&quot;:&quot;ai&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">AI</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=software-development" data-analytics-event="{&quot;action&quot;:&quot;software_development&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Software Development</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=security" data-analytics-event="{&quot;action&quot;:&quot;security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources/articles" data-analytics-event="{&quot;action&quot;:&quot;view_all_topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_topics_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all topics</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9lnd_">EXPLORE BY TYPE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/customer-stories" data-analytics-event="{&quot;action&quot;:&quot;customer_stories&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer stories</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/events" data-analytics-event="{&quot;action&quot;:&quot;events__webinars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;events__webinars_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Events &amp; webinars</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/whitepapers" data-analytics-event="{&quot;action&quot;:&quot;ebooks__reports&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ebooks__reports_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Ebooks &amp; reports</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/executive-insights" data-analytics-event="{&quot;action&quot;:&quot;business_insights&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;business_insights_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Business insights</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://skills.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_skills&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_skills_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Skills</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dlnd_">SUPPORT &amp; SERVICES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dlnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://support.github.com" data-analytics-event="{&quot;action&quot;:&quot;customer_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_support_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer support</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/orgs/community/discussions" data-analytics-event="{&quot;action&quot;:&quot;community_forum&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;community_forum_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Community forum</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trust-center" data-analytics-event="{&quot;action&quot;:&quot;trust_center&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trust_center_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trust center</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/partners" data-analytics-event="{&quot;action&quot;:&quot;partners&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Partners</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources" data-analytics-event="{&quot;action&quot;:&quot;view_all_resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_resources_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all resources</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_27d_">Open Source<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_27d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5m7d_">COMMUNITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/open-source/sponsors" data-analytics-event="{&quot;action&quot;:&quot;github_sponsors&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sponsor-tiers NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.586 1C12.268 1 13.5 2.37 13.5 4.25c0 1.745-.996 3.359-2.622 4.831-.166.15-.336.297-.509.438l1.116 5.584a.75.75 0 0 1-.991.852l-2.409-.876a.25.25 0 0 0-.17 0l-2.409.876a.75.75 0 0 1-.991-.852L5.63 9.519a13.78 13.78 0 0 1-.51-.438C3.497 7.609 2.5 5.995 2.5 4.25 2.5 2.37 3.732 1 5.414 1c.963 0 1.843.403 2.474 1.073L8 2.198l.112-.125a3.385 3.385 0 0 1 2.283-1.068L10.586 1Zm-3.621 9.495-.718 3.594 1.155-.42a1.75 1.75 0 0 1 1.028-.051l.168.051 1.154.42-.718-3.592c-.199.13-.37.235-.505.314l-.169.097a.75.75 0 0 1-.72 0 9.54 9.54 0 0 1-.515-.308l-.16-.105ZM10.586 2.5c-.863 0-1.611.58-1.866 1.459-.209.721-1.231.721-1.44 0C7.025 3.08 6.277 2.5 5.414 2.5 4.598 2.5 4 3.165 4 4.25c0 1.23.786 2.504 2.128 3.719.49.443 1.018.846 1.546 1.198l.325.21.076-.047.251-.163a13.341 13.341 0 0 0 1.546-1.198C11.214 6.754 12 5.479 12 4.25c0-1.085-.598-1.75-1.414-1.75Z"></path></svg>GitHub Sponsors</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Fund open source developers</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9m7d_">PROGRAMS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://securitylab.github.com" data-analytics-event="{&quot;action&quot;:&quot;security_lab&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_lab_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security Lab</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://maintainers.github.com" data-analytics-event="{&quot;action&quot;:&quot;maintainer_community&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;maintainer_community_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Maintainer Community</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://stars.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_stars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_stars_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Stars</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://archiveprogram.github.com" data-analytics-event="{&quot;action&quot;:&quot;archive_program&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;archive_program_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Archive Program</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dm7d_">REPOSITORIES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dm7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/topics" data-analytics-event="{&quot;action&quot;:&quot;topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Topics</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trending" data-analytics-event="{&quot;action&quot;:&quot;trending&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trending</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/collections" data-analytics-event="{&quot;action&quot;:&quot;collections&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Collections</span></a></li></ul></div></li></ul></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_2nd_">Enterprise<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_2nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5mnd_">ENTERPRISE SOLUTIONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-stack NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.122.392a1.75 1.75 0 0 1 1.756 0l5.003 2.902c.83.481.83 1.68 0 2.162L8.878 8.358a1.75 1.75 0 0 1-1.756 0L2.119 5.456a1.251 1.251 0 0 1 0-2.162ZM8.125 1.69a.248.248 0 0 0-.25 0l-4.63 2.685 4.63 2.685a.248.248 0 0 0 .25 0l4.63-2.685ZM1.601 7.789a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0L1.874 8.814A.75.75 0 0 1 1.6 7.789Zm0 3.5a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0l-5.248-3.044a.75.75 0 0 1-.273-1.025Z"></path></svg>Enterprise platform</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">AI-powered developer platform</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9mnd_">AVAILABLE ADD-ONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade security features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot/copilot-business" data-analytics-event="{&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>Copilot for Business</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade AI features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise/premium-support" data-analytics-event="{&quot;action&quot;:&quot;premium_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg>Premium Support</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade 24/7 support</span></span></a></li></ul></div></li></ul></div></div></li><li><a href="https://github.com/pricing" data-analytics-event="{&quot;action&quot;:&quot;pricing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;pricing&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;pricing_link_pricing_navbar&quot;}" class="MarketingNavigation-module__navLink__hUomM">Pricing</a></li></ul></nav><div class="MarketingHeader-module__ctaContainer__tBmPz"><div class="HeaderSearch-module__searchSlot__oVOUS"><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderSearch-module__trigger__zsF9q" type="button" aria-haspopup="dialog" aria-expanded="false" aria-label="Search or jump to, type / to search" data-analytics-event="{&quot;action&quot;:&quot;searchbar&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;context&quot;:&quot;global&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"><span class="HeaderSearch-module__content__kMpxU"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search HeaderSearch-module__icon__wcrHX" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg><span class="HeaderSearch-module__label__d1iWG">Search</span><kbd class="HeaderSearch-module__kbd__HNG0o" aria-hidden="true">/</kbd></span></span></span></button><div class="d-none"></div></div><div class="AuthCTAs-module__signInWrap__q2P60"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq AuthCTAs-module__desktopActionGap__UZuXT AuthCTAs-module__hiddenBelowLg__BfKBw" href="/login?return_to=https%3A%2F%2Fgithub.com%2FCodingDocs%2Fspringboot-guide%2Fblob%2Fmaster%2Fdocs%2FMyBatisPlus.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e68cad6441adef570167d364ec2fcc10b746def6fb84e42c2fdceeef934d01cd"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a></div><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--secondary___gHnw_ Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&amp;source=header-repo&amp;source_repo=CodingDocs%2Fspringboot-guide" data-analytics-event="{&quot;action&quot;:&quot;sign_up&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_up_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e68cad6441adef570167d364ec2fcc10b746def6fb84e42c2fdceeef934d01cd"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-secondary___eJ0_a">Sign up</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_fbd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_fbd_">Appearance settings</div></div></div></div></div><div class="MarketingHeader-module__bottomBorder__uZT38" aria-hidden="true"></div></header></div></div>
</react-partial>



      <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full">
  
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>

    <button id="icon-button-fd593ab9-0d9b-417c-954f-1a0fb6a4a5b4" aria-labelledby="tooltip-262912d0-b5cc-4d55-bcd1-e27b49c79f3d" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close">  <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
</button><tool-tip id="tooltip-262912d0-b5cc-4d55-bcd1-e27b49c79f3d" for="icon-button-fd593ab9-0d9b-417c-954f-1a0fb6a4a5b4" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip>


  
</div>
    </div>

  <div id="start-of-content" class="show-on-focus"></div>








    <div id="js-flash-container" class="flash-container" data-turbo-replace>





  <template class="js-flash-template">
    
<div class="flash flash-full   {{ className }}">
  <div >
    <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    <div aria-atomic="true" role="alert" class="js-flash-alert">
      
      <div>{{ message }}</div>

    </div>
  </div>
</div>
  </template>
</div>


    






  <div
    class="application-main "
    data-commit-hovercards-enabled
    data-discussion-hovercards-enabled
    data-issue-and-pr-hovercards-enabled
    data-project-hovercards-enabled
  >
        <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class="">
    <main id="js-repo-pjax-container" >
      
      
    


    








  

    <div id="repository-container-header"  class="tmp-pt-3 hide-full-screen" style="background-color: var(--page-header-bgColor, var(--color-page-header-bg));" data-turbo-replace>

        <div class="d-flex flex-nowrap flex-justify-end tmp-mb-3  tmp-px-3 tmp-px-lg-5" style="gap: 1rem;">

          <div class="flex-auto min-width-0 width-fit">
              
  <div class=" d-flex flex-wrap flex-items-center wb-break-word f3 text-normal">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo color-fg-muted mr-2 tmp-mr-2">
    <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path>
</svg>
    
    <span class="author flex-self-stretch" itemprop="author">
      <a class="url fn" rel="author" data-hovercard-type="organization" data-hovercard-url="/orgs/CodingDocs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/CodingDocs">
        CodingDocs
</a>    </span>
    <span class="mx-1 flex-self-stretch color-fg-muted">/</span>
    <strong itemprop="name" class="mr-2 flex-self-stretch">
      <a data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="/CodingDocs/springboot-guide">springboot-guide</a>
    </strong>

    <span></span><span class="Label Label--secondary v-align-middle mr-1">Public</span>
  </div>


          </div>

          <div id="repository-details-container" class="flex-shrink-0" data-turbo-replace style="max-width: 70%;">
              <ul class="pagehead-actions flex-shrink-0 d-none d-md-inline" style="padding: 2px 0;">
    
      

  <li>
            <a href="/login?return_to=%2FCodingDocs%2Fspringboot-guide" rel="nofollow" id="repository-details-watch-button" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;notification subscription menu watch&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="034085881dee8fc4103a79dacc8ed367ed757ee098e55434adc30c9435e06004" aria-label="You must be signed in to change notification settings" data-view-component="true" class="btn-sm btn">    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bell mr-2 tmp-mr-2">
    <path d="M8 16a2 2 0 0 0 1.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 0 0 8 16ZM3 5a5 5 0 0 1 10 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.519 1.519 0 0 1 13.482 13H2.518a1.516 1.516 0 0 1-1.263-2.36l1.703-2.554A.255.255 0 0 0 3 7.947Zm5-3.5A3.5 3.5 0 0 0 4.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.017.017 0 0 0-.003.01l.001.006c0 .002.002.004.004.006l.006.004.007.001h10.964l.007-.001.006-.004.004-.006.001-.007a.017.017 0 0 0-.003-.01l-1.703-2.554a1.745 1.745 0 0 1-.294-.97V5A3.5 3.5 0 0 0 8 1.5Z"></path>
</svg>Notifications
</a>    <tool-tip id="tooltip-c9216423-6ac6-42d5-abbb-9fa20446f47b" for="repository-details-watch-button" popover="manual" data-direction="s" data-type="description" data-view-component="true" class="sr-only position-absolute">You must be signed in to change notification settings</tool-tip>

  </li>

  <li>
          <a icon="repo-forked" id="fork-button" href="/login?return_to=%2FCodingDocs%2Fspringboot-guide" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;repo details fork button&quot;,&quot;repository_id&quot;:159422409,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="6c810d9028b56466f536a2fa53328ef5d393ece3542eeb44306f7a8567997bd7" data-view-component="true" class="btn-sm btn">    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo-forked mr-2 tmp-mr-2">
    <path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path>
</svg>Fork
    <span id="repo-network-counter" data-pjax-replace="true" data-turbo-replace="true" title="1,391" data-view-component="true" class="Counter">1.4k</span>
</a>
  </li>

  <li>
        <div data-view-component="true" class="BtnGroup d-flex">
        <a href="/login?return_to=%2FCodingDocs%2Fspringboot-guide" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;star button&quot;,&quot;repository_id&quot;:159422409,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="40add33347568c14d9b006d459e413d425a7658c97bab35cc59fd545586f277a" aria-label="You must be signed in to star a repository" data-view-component="true" class="tooltipped tooltipped-sw btn-sm btn">    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star v-align-text-bottom d-inline-block mr-2 tmp-mr-2">
    <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path>
</svg><span data-view-component="true" class="d-inline">
          Star
</span>          <span id="repo-stars-counter-star" aria-label="5263 users starred this repository" data-singular-suffix="user starred this repository" data-plural-suffix="users starred this repository" data-turbo-replace="true" title="5,263" data-view-component="true" class="Counter js-social-count">5.3k</span>
</a></div>
  </li>

</ul>

          </div>
        </div>

          <div id="responsive-meta-container" data-turbo-replace>
</div>


            <nav data-pjax="#js-repo-pjax-container" aria-label="Repository" data-view-component="true" class="js-repo-nav js-sidenav-container-pjax js-responsive-underlinenav overflow-hidden UnderlineNav px-3 tmp-px-3 px-md-4 tmp-px-md-4 px-lg-5 tmp-px-lg-5">

  <ul data-view-component="true" class="UnderlineNav-body list-style-none">
      <li data-view-component="true" class="d-inline-flex">
  <a id="code-tab" href="/CodingDocs/springboot-guide" data-tab-item="i0code-tab" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages repo_deployments repo_attestations /CodingDocs/springboot-guide" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g c" data-command-id="repositories:go-to-code" data-react-nav="code-view" data-react-nav-anchor="code-view-repo-link" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Code&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" aria-current="page" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item selected">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code UnderlineNav-octicon d-none d-sm-inline">
    <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path>
</svg>
        <span data-content="Code">Code</span>
          <span id="code-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span>


    
</a></li>
      <li data-view-component="true" class="d-inline-flex">
  <a id="issues-tab" href="/CodingDocs/springboot-guide/issues" data-tab-item="i1issues-tab" data-selected-links="repo_issues repo_labels repo_milestones /CodingDocs/springboot-guide/issues" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g i" data-command-id="repositories:go-to-issues" data-react-nav="issues-react" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Issues&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened UnderlineNav-octicon d-none d-sm-inline">
    <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path>
</svg>
        <span data-content="Issues">Issues</span>
          <span id="issues-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="13" data-view-component="true" class="Counter">13</span>


    
</a></li>
      <li data-view-component="true" class="d-inline-flex">
  <a id="pull-requests-tab" href="/CodingDocs/springboot-guide/pulls" data-tab-item="i2pull-requests-tab" data-selected-links="repo_pulls checks /CodingDocs/springboot-guide/pulls" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g p" data-command-id="repositories:go-to-pull-requests" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Pull requests&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request UnderlineNav-octicon d-none d-sm-inline">
    <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path>
</svg>
        <span data-content="Pull requests">Pull requests</span>
          <span id="pull-requests-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="3" data-view-component="true" class="Counter">3</span>


    
</a></li>
      <li data-view-component="true" class="d-inline-flex">
  <a id="actions-tab" href="/CodingDocs/springboot-guide/actions" data-tab-item="i3actions-tab" data-selected-links="repo_actions /CodingDocs/springboot-guide/actions" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g a" data-command-id="repositories:go-to-actions" data-react-nav="actions-workflows" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Actions&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play UnderlineNav-octicon d-none d-sm-inline">
    <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path>
</svg>
        <span data-content="Actions">Actions</span>
          <span id="actions-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span>


    
</a></li>
      <li data-view-component="true" class="d-inline-flex">
  <a id="projects-tab" href="/CodingDocs/springboot-guide/projects" data-tab-item="i4projects-tab" data-selected-links="repo_projects new_repo_project repo_project /CodingDocs/springboot-guide/projects" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g b" data-command-id="repositories:go-to-projects" data-react-nav="repo" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Projects&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-table UnderlineNav-octicon d-none d-sm-inline">
    <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path>
</svg>
        <span data-content="Projects">Projects</span>
          <span id="projects-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span>


    
</a></li>
      <li data-view-component="true" class="d-inline-flex">
  <a id="security-and-quality-tab" href="/CodingDocs/springboot-guide/security" data-tab-item="i5security-and-quality-tab" data-selected-links="security overview alerts policy token_scanning code_scanning /CodingDocs/springboot-guide/security" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g s" data-command-id="repositories:go-to-security" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Security and quality&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield UnderlineNav-octicon d-none d-sm-inline">
    <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        <span data-content="Security and quality">Security and quality</span>
          <span id="security-and-quality-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="0" hidden="hidden" data-view-component="true" class="Counter">0</span>


    
</a></li>
      <li data-view-component="true" class="d-inline-flex">
  <a id="insights-tab" href="/CodingDocs/springboot-guide/pulse" data-tab-item="i6insights-tab" data-selected-links="repo_graphs repo_contributors dependency_graph dependabot_updates pulse people community /CodingDocs/springboot-guide/pulse" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-command-id="repositories:go-to-insights" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Insights&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item">
    
              <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph UnderlineNav-octicon d-none d-sm-inline">
    <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path>
</svg>
        <span data-content="Insights">Insights</span>
          <span id="insights-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span>


    
</a></li>
</ul>
    <div style="visibility:hidden;" data-view-component="true" class="UnderlineNav-actions js-responsive-underlinenav-overflow position-absolute pr-3 tmp-pr-3 pr-md-4 tmp-pr-md-4 pr-lg-5 tmp-pr-lg-5 right-0">      <action-menu data-select-variant="none" data-view-component="true">
  <focus-group direction="vertical" mnemonics retain>
    <button id="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-button" popovertarget="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-overlay" aria-controls="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-list" aria-haspopup="true" aria-labelledby="tooltip-bb21b220-e9d8-49d9-bc30-57557ca5a4e4" type="button" data-view-component="true" class="Button Button--iconOnly Button--secondary Button--medium UnderlineNav-item">  <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-kebab-horizontal Button-visual">
    <path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path>
</svg>
</button><tool-tip id="tooltip-bb21b220-e9d8-49d9-bc30-57557ca5a4e4" for="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-button" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Additional navigation options</tool-tip>


<anchored-position data-target="action-menu.overlay" id="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-overlay" anchor="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-button" align="start" side="outside-bottom" anchor-offset="normal" popover="auto" data-view-component="true">
  <div data-view-component="true" class="Overlay Overlay--size-auto">
    
      <div data-view-component="true" class="Overlay-body Overlay-body--paddingNone">          <action-list>
  <div data-view-component="true">
    <ul aria-labelledby="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-button" id="action-menu-e8345454-ad67-46b8-ab74-f1709a7778ff-list" role="menu" data-view-component="true" class="ActionListWrap--inset ActionListWrap">
        <li hidden="hidden" data-menu-item="i0code-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-7770732d-1a49-4b53-9889-dcff8463eccf" href="/CodingDocs/springboot-guide" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code">
    <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Code
</span>      
</a>
  
</li>
        <li hidden="hidden" data-menu-item="i1issues-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-31b4a0f2-b602-49aa-a16f-052d07676e91" href="/CodingDocs/springboot-guide/issues" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened">
    <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Issues
</span>      
</a>
  
</li>
        <li hidden="hidden" data-menu-item="i2pull-requests-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-a5e326de-86d1-4b85-be31-0b1cfb1bc57a" href="/CodingDocs/springboot-guide/pulls" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request">
    <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Pull requests
</span>      
</a>
  
</li>
        <li hidden="hidden" data-menu-item="i3actions-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-4178cf72-3243-4098-9e4b-a791efd318f1" href="/CodingDocs/springboot-guide/actions" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play">
    <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Actions
</span>      
</a>
  
</li>
        <li hidden="hidden" data-menu-item="i4projects-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-b457ccb8-5eaa-434c-9b3c-28bac30cdedf" href="/CodingDocs/springboot-guide/projects" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-table">
    <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Projects
</span>      
</a>
  
</li>
        <li hidden="hidden" data-menu-item="i5security-and-quality-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-679e259e-22d6-496b-8be8-1d1edced3f4d" href="/CodingDocs/springboot-guide/security" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield">
    <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Security and quality
</span>      
</a>
  
</li>
        <li hidden="hidden" data-menu-item="i6insights-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem">
    
    
    <a tabindex="-1" id="item-27a53fd3-0e3a-4f54-be5a-30cda609b2d8" href="/CodingDocs/springboot-guide/pulse" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16">
        <span class="ActionListItem-visual ActionListItem-visual--leading">
          <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph">
    <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path>
</svg>
        </span>
      
        <span data-view-component="true" class="ActionListItem-label">
          Insights
</span>      
</a>
  
</li>
</ul>    
</div></action-list>


</div>
      
</div></anchored-position>  </focus-group>
</action-menu></div>
</nav>

    </div>
  



<turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class="">
    <div id="repo-content-pjax-container" class="repository-content " >
    



    
      
    








<react-app
  app-name="code-view"
  initial-path="/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md"
  style="display: block; min-height: calc(100vh - 64px);"
  data-attempted-ssr="true"
  data-ssr="true"
  data-lazy="false"
  data-alternate="false"
  data-data-router-enabled="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-app.embeddedData">{"payload":{"codeViewBlobRoute":{"csv":null,"csvError":null,"headerInfo":{"toc":[{"level":2,"text":"CRUD","anchor":"crud","htmlText":"CRUD"},{"level":2,"text":"ID 策略","anchor":"id-策略","htmlText":"ID 策略"},{"level":2,"text":"属性自动填充","anchor":"属性自动填充","htmlText":"属性自动填充"},{"level":2,"text":"逻辑删除","anchor":"逻辑删除","htmlText":"逻辑删除"},{"level":2,"text":"分页插件","anchor":"分页插件","htmlText":"分页插件"},{"level":2,"text":"乐观锁","anchor":"乐观锁","htmlText":"乐观锁"},{"level":2,"text":"条件构造器","anchor":"条件构造器","htmlText":"条件构造器"}]},"issueTemplate":null,"discussionTemplate":null,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cp dir=\"auto\"\u003e\u003ccode\u003eMyBatis\u003c/code\u003e 是一款优秀的持久层框架，它支持定制化 SQL、存储过程以及高级映射，而实际开发中，我们都会选择使用 \u003ccode\u003eMyBatisPlus\u003c/code\u003e，它是对 \u003ccode\u003eMyBatis\u003c/code\u003e 框架的进一步增强，能够极大地简化我们的持久层代码，下面就一起来看看 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 中的一些奇淫巧技吧。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e说明：本篇文章需要一定的 \u003ccode\u003eMyBatis\u003c/code\u003e 与 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 基础\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp dir=\"auto\"\u003eMyBatis-Plus 官网地址 ： \u003ca href=\"https://baomidou.com/\" rel=\"nofollow\"\u003ehttps://baomidou.com/\u003c/a\u003e 。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCRUD\u003c/h2\u003e\u003ca id=\"user-content-crud\" class=\"anchor\" aria-label=\"Permalink: CRUD\" href=\"#crud\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e使用 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 实现业务的增删改查非常地简单，一起来看看吧。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e1.首先新建一个 SpringBoot 工程，然后引入依赖：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-text-xml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"\u0026lt;dependency\u0026gt;\n  \u0026lt;groupId\u0026gt;com.baomidou\u0026lt;/groupId\u0026gt;\n  \u0026lt;artifactId\u0026gt;mybatis-plus-boot-starter\u0026lt;/artifactId\u0026gt;\n  \u0026lt;version\u0026gt;3.4.2\u0026lt;/version\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u0026lt;dependency\u0026gt;\n  \u0026lt;groupId\u0026gt;mysql\u0026lt;/groupId\u0026gt;\n  \u0026lt;artifactId\u0026gt;mysql-connector-java\u0026lt;/artifactId\u0026gt;\n  \u0026lt;scope\u0026gt;runtime\u0026lt;/scope\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u0026lt;dependency\u0026gt;\n  \u0026lt;groupId\u0026gt;org.projectlombok\u0026lt;/groupId\u0026gt;\n  \u0026lt;artifactId\u0026gt;lombok\u0026lt;/artifactId\u0026gt;\n\u0026lt;/dependency\u0026gt;\"\u003e\u003cpre\u003e\u0026lt;\u003cspan class=\"pl-ent\"\u003edependency\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003egroupId\u003c/span\u003e\u0026gt;com.baomidou\u0026lt;/\u003cspan class=\"pl-ent\"\u003egroupId\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003eartifactId\u003c/span\u003e\u0026gt;mybatis-plus-boot-starter\u0026lt;/\u003cspan class=\"pl-ent\"\u003eartifactId\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003eversion\u003c/span\u003e\u0026gt;3.4.2\u0026lt;/\u003cspan class=\"pl-ent\"\u003eversion\u003c/span\u003e\u0026gt;\n\u0026lt;/\u003cspan class=\"pl-ent\"\u003edependency\u003c/span\u003e\u0026gt;\n\u0026lt;\u003cspan class=\"pl-ent\"\u003edependency\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003egroupId\u003c/span\u003e\u0026gt;mysql\u0026lt;/\u003cspan class=\"pl-ent\"\u003egroupId\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003eartifactId\u003c/span\u003e\u0026gt;mysql-connector-java\u0026lt;/\u003cspan class=\"pl-ent\"\u003eartifactId\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003escope\u003c/span\u003e\u0026gt;runtime\u0026lt;/\u003cspan class=\"pl-ent\"\u003escope\u003c/span\u003e\u0026gt;\n\u0026lt;/\u003cspan class=\"pl-ent\"\u003edependency\u003c/span\u003e\u0026gt;\n\u0026lt;\u003cspan class=\"pl-ent\"\u003edependency\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003egroupId\u003c/span\u003e\u0026gt;org.projectlombok\u0026lt;/\u003cspan class=\"pl-ent\"\u003egroupId\u003c/span\u003e\u0026gt;\n  \u0026lt;\u003cspan class=\"pl-ent\"\u003eartifactId\u003c/span\u003e\u0026gt;lombok\u0026lt;/\u003cspan class=\"pl-ent\"\u003eartifactId\u003c/span\u003e\u0026gt;\n\u0026lt;/\u003cspan class=\"pl-ent\"\u003edependency\u003c/span\u003e\u0026gt;\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e2.配置一下数据源：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"spring:\n  datasource:\n    driver-class-name: com.mysql.cj.jdbc.Driver\n    username: root\n    url: jdbc:mysql:///mybatisplus?serverTimezone=UTC\n    password: 123456\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ent\"\u003espring\u003c/span\u003e:\n  \u003cspan class=\"pl-ent\"\u003edatasource\u003c/span\u003e:\n    \u003cspan class=\"pl-ent\"\u003edriver-class-name\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003ecom.mysql.cj.jdbc.Driver\u003c/span\u003e\n    \u003cspan class=\"pl-ent\"\u003eusername\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003eroot\u003c/span\u003e\n    \u003cspan class=\"pl-ent\"\u003eurl\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003ejdbc:mysql:///mybatisplus?serverTimezone=UTC\u003c/span\u003e\n    \u003cspan class=\"pl-ent\"\u003epassword\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e123456\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e3.创建一下数据表：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"CREATE DATABASE `mybatisplus`;\n\nUSE `mybatisplus`;\n\nDROP TABLE IF EXISTS `tbl_employee`;\n\nCREATE TABLE `tbl_employee` (\n  `id` bigint(20) NOT NULL,\n  `last_name` varchar(255) DEFAULT NULL,\n  `email` varchar(255) DEFAULT NULL,\n  `gender` char(1) DEFAULT NULL,\n  `age` int(11) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=gbk;\n\ninsert  into `tbl_employee`(`id`,`last_name`,`email`,`gender`,`age`) values (1,'jack','jack@qq.com','1',35),(2,'tom','tom@qq.com','1',30),(3,'jerry','jerry@qq.com','1',40);\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003eCREATE\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eDATABASE\u003c/span\u003e `\u003cspan class=\"pl-en\"\u003emybatisplus\u003c/span\u003e`;\n\nUSE \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003emybatisplus\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e;\n\n\u003cspan class=\"pl-k\"\u003eDROP\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eTABLE\u003c/span\u003e IF EXISTS \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003etbl_employee\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e;\n\n\u003cspan class=\"pl-k\"\u003eCREATE\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eTABLE\u003c/span\u003e `\u003cspan class=\"pl-en\"\u003etbl_employee\u003c/span\u003e` (\n  \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eid\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-k\"\u003ebigint\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e) \u003cspan class=\"pl-k\"\u003eNOT NULL\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003elast_name\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-k\"\u003evarchar\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e255\u003c/span\u003e) DEFAULT \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eemail\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-k\"\u003evarchar\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e255\u003c/span\u003e) DEFAULT \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003egender\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-k\"\u003echar\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e) DEFAULT \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e,\n  \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eage\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eint\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e) DEFAULT \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e,\n  \u003cspan class=\"pl-k\"\u003ePRIMARY KEY\u003c/span\u003e (\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eid\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e)\n) ENGINE\u003cspan class=\"pl-k\"\u003e=\u003c/span\u003eInnoDB AUTO_INCREMENT\u003cspan class=\"pl-k\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e8\u003c/span\u003e DEFAULT CHARSET\u003cspan class=\"pl-k\"\u003e=\u003c/span\u003egbk;\n\n\u003cspan class=\"pl-k\"\u003einsert  into\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003etbl_employee\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eid\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003elast_name\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eemail\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003egender\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003eage\u003cspan class=\"pl-pds\"\u003e`\u003c/span\u003e\u003c/span\u003e) \u003cspan class=\"pl-k\"\u003evalues\u003c/span\u003e (\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ejack\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ejack@qq.com\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e1\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e),(\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003etom\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003etom@qq.com\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e1\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e),(\u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ejerry\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ejerry@qq.com\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e1\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-c1\"\u003e40\u003c/span\u003e);\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e4.创建对应的实体类：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\npublic class Employee {\n\n    private Long id;\n    private String lastName;\n    private String email;\n    private Integer age;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e {\n\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e4.编写 \u003ccode\u003eMapper\u003c/code\u003e 接口：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public interface EmployeeMapper extends BaseMapper\u0026lt;Employee\u0026gt; {\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeMapper\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eBaseMapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; {\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e我们只需继承 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 提供的 \u003ccode\u003eBaseMapper\u003c/code\u003e 接口即可，现在我们就拥有了对 \u003ccode\u003eEmployee\u003c/code\u003e 进行增删改查的 API，比如：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@SpringBootTest\n@MapperScan(\u0026quot;com.wwj.mybatisplusdemo.mapper\u0026quot;)\nclass MybatisplusDemoApplicationTests {\n\n    @Autowired\n    private EmployeeMapper employeeMapper;\n\n    @Test\n    void contextLoads() {\n        List\u0026lt;Employee\u0026gt; employees = employeeMapper.selectList(null);\n        employees.forEach(System.out::println);\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSpringBootTest\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eMapperScan\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"com.wwj.mybatisplusdemo.mapper\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisplusDemoApplicationTests\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eAutowired\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeMapper\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e;\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n        \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003eemployees\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectList\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e);\n        \u003cspan class=\"pl-s1\"\u003eemployees\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"org.springframework.jdbc.BadSqlGrammarException:\n### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'mybatisplus.employee' doesn't exist\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eorg\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003espringframework\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003ejdbc\u003c/span\u003e.\u003cspan class=\"pl-smi\"\u003eBadSqlGrammarException\u003c/span\u003e:\n### \u003cspan class=\"pl-s1\"\u003eError\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003equerying\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edatabase\u003c/span\u003e.  \u003cspan class=\"pl-s1\"\u003eCause\u003c/span\u003e: \u003cspan class=\"pl-s1\"\u003ejava\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003esql\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eSQLSyntaxErrorException\u003c/span\u003e: \u003cspan class=\"pl-s1\"\u003eTable\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e'mybatisplus.employee'\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edoesn\u003c/span\u003e't exist\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e程序报错了，原因是不存在 \u003ccode\u003eemployee\u003c/code\u003e 表，这是因为我们的实体类名为 \u003ccode\u003eEmployee\u003c/code\u003e，\u003ccode\u003eMyBatisPlus\u003c/code\u003e 默认是以类名作为表名进行操作的，可如果类名和表名不相同（实际开发中也确实可能不同），就需要在实体类中使用 \u003ccode\u003e@TableName\u003c/code\u003e 注解来声明表的名称：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\n@TableName(\u0026quot;tbl_employee\u0026quot;) // 声明表名称\npublic class Employee {\n\n    private Long id;\n    private String lastName;\n    private String email;\n    private Integer age;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"tbl_employee\"\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e// 声明表名称\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e {\n\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e重新执行测试代码，结果如下：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Employee(id=1, lastName=jack, email=jack@qq.com, age=35)\nEmployee(id=2, lastName=tom, email=tom@qq.com, age=30)\nEmployee(id=3, lastName=jerry, email=jerry@qq.com, age=40)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejack\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003etom\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejerry\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejerry\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e40\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eBaseMapper\u003c/code\u003e 提供了常用的一些增删改查方法：\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/24a7bb0b0c749eb3802222eab0c417f092e4e3770995343de1a248ee926a3987/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343035393836352e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/24a7bb0b0c749eb3802222eab0c417f092e4e3770995343de1a248ee926a3987/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343035393836352e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210519084059865.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e具体细节可以查阅其源码自行体会，注释都是中文的，非常容易理解。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e在开发过程中，我们通常会使用 \u003ccode\u003eService\u003c/code\u003e 层来调用 \u003ccode\u003eMapper\u003c/code\u003e 层的方法，而 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 也为我们提供了通用的 \u003ccode\u003eService\u003c/code\u003e：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public interface EmployeeService extends IService\u0026lt;Employee\u0026gt; {\n}\n\n@Service\npublic class EmployeeServiceImpl extends ServiceImpl\u0026lt;EmployeeMapper, Employee\u0026gt; implements EmployeeService {\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeService\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eIService\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; {\n}\n\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eService\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeServiceImpl\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eServiceImpl\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployeeMapper\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeService\u003c/span\u003e {\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e事实上，我们只需让 \u003ccode\u003eEmployeeServiceImpl\u003c/code\u003e 继承 \u003ccode\u003eServiceImpl\u003c/code\u003e 即可获得 \u003ccode\u003eService\u003c/code\u003e 层的方法，\u003cstrong\u003e那么为什么还需要实现 \u003ccode\u003eEmployeeService\u003c/code\u003e 接口呢？\u003c/strong\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e这是因为实现 \u003ccode\u003eEmployeeService\u003c/code\u003e 接口能够更方便地对业务进行扩展，一些复杂场景下的数据处理，\u003ccode\u003eMyBatisPlus\u003c/code\u003e 提供的 \u003ccode\u003eService\u003c/code\u003e 方法可能无法处理，此时我们就需要自己编写代码，这时候只需在 \u003ccode\u003eEmployeeService\u003c/code\u003e 中定义自己的方法，并在 \u003ccode\u003eEmployeeServiceImpl\u003c/code\u003e 中实现即可。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e先来测试一下 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 提供的 \u003ccode\u003eService\u003c/code\u003e 方法：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@SpringBootTest\n@MapperScan(\u0026quot;com.wwj.mybatisplusdemo.mapper\u0026quot;)\nclass MybatisplusDemoApplicationTests {\n\n    @Autowired\n    private EmployeeService employeeService;\n\n    @Test\n    void contextLoads() {\n        List\u0026lt;Employee\u0026gt; list = employeeService.list();\n        list.forEach(System.out::println);\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSpringBootTest\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eMapperScan\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"com.wwj.mybatisplusdemo.mapper\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisplusDemoApplicationTests\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eAutowired\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeService\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e;\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n        \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003elist\u003c/span\u003e();\n        \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Employee(id=1, lastName=jack, email=jack@qq.com, age=35)\nEmployee(id=2, lastName=tom, email=tom@qq.com, age=30)\nEmployee(id=3, lastName=jerry, email=jerry@qq.com, age=40)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejack\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003etom\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejerry\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejerry\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e40\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e接下来模拟一个自定义的场景，我们来编写自定义的操作方法，首先在 \u003ccode\u003eEmployeeMapper\u003c/code\u003e 中进行声明：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public interface EmployeeMapper extends BaseMapper\u0026lt;Employee\u0026gt; {\n\n    List\u0026lt;Employee\u0026gt; selectAllByLastName(@Param(\u0026quot;lastName\u0026quot;) String lastName);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeMapper\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eBaseMapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; {\n\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-en\"\u003eselectAllByLastName\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eParam\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"lastName\"\u003c/span\u003e) \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e此时我们需要自己编写配置文件实现该方法，在 \u003ccode\u003eresource\u003c/code\u003e 目录下新建一个 \u003ccode\u003emapper\u003c/code\u003e 文件夹，然后在该文件夹下创建 \u003ccode\u003eEmployeeMapper.xml\u003c/code\u003e 文件：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-text-xml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"\u0026lt;!DOCTYPE mapper\n        PUBLIC \u0026quot;-//mybatis.org//DTD Mapper 3.0//EN\u0026quot;\n        \u0026quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd\u0026quot;\u0026gt;\n\n\u0026lt;mapper namespace=\u0026quot;com.wwj.mybatisplusdemo.mapper.EmployeeMapper\u0026quot;\u0026gt;\n\n    \u0026lt;sql id=\u0026quot;Base_Column\u0026quot;\u0026gt;\n        id, last_name, email, gender, age\n    \u0026lt;/sql\u0026gt;\n\n    \u0026lt;select id=\u0026quot;selectAllByLastName\u0026quot; resultType=\u0026quot;com.wwj.mybatisplusdemo.bean.Employee\u0026quot;\u0026gt;\n        select \u0026lt;include refid=\u0026quot;Base_Column\u0026quot;/\u0026gt;\n        from tbl_employee\n        where last_name = #{lastName}\n    \u0026lt;/select\u0026gt;\n\u0026lt;/mapper\u0026gt;\"\u003e\u003cpre\u003e\u0026lt;!\u003cspan class=\"pl-ent\"\u003eDOCTYPE\u003c/span\u003e \u003cspan class=\"pl-e\"\u003emapper\u003c/span\u003e\n        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"\u0026gt;\n\n\u0026lt;\u003cspan class=\"pl-ent\"\u003emapper\u003c/span\u003e \u003cspan class=\"pl-e\"\u003enamespace\u003c/span\u003e=\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003ecom.wwj.mybatisplusdemo.mapper.EmployeeMapper\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u0026gt;\n\n    \u0026lt;\u003cspan class=\"pl-ent\"\u003esql\u003c/span\u003e \u003cspan class=\"pl-e\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eBase_Column\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u0026gt;\n        id, last_name, email, gender, age\n    \u0026lt;/\u003cspan class=\"pl-ent\"\u003esql\u003c/span\u003e\u0026gt;\n\n    \u0026lt;\u003cspan class=\"pl-ent\"\u003eselect\u003c/span\u003e \u003cspan class=\"pl-e\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eselectAllByLastName\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-e\"\u003eresultType\u003c/span\u003e=\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003ecom.wwj.mybatisplusdemo.bean.Employee\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u0026gt;\n        select \u0026lt;\u003cspan class=\"pl-ent\"\u003einclude\u003c/span\u003e \u003cspan class=\"pl-e\"\u003erefid\u003c/span\u003e=\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eBase_Column\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e/\u0026gt;\n        from tbl_employee\n        where last_name = #{lastName}\n    \u0026lt;/\u003cspan class=\"pl-ent\"\u003eselect\u003c/span\u003e\u0026gt;\n\u0026lt;/\u003cspan class=\"pl-ent\"\u003emapper\u003c/span\u003e\u0026gt;\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eMyBatisPlus\u003c/code\u003e 默认扫描的是类路径下的 \u003ccode\u003emapper\u003c/code\u003e 目录，这可以从源码中得到体现：\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/3a645e2cb6435f646d7175e6fc04931047ec4c3b214d46e7dcd5d71a782d0ec3/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343034363437322e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/3a645e2cb6435f646d7175e6fc04931047ec4c3b214d46e7dcd5d71a782d0ec3/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343034363437322e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210519084046472.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e所以我们直接将 \u003ccode\u003eMapper\u003c/code\u003e 配置文件放在该目录下就没有任何问题，可如果不是这个目录，我们就需要进行配置，比如：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"mybatis-plus:\n  mapper-locations: classpath:xml/*.xml\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ent\"\u003emybatis-plus\u003c/span\u003e:\n  \u003cspan class=\"pl-ent\"\u003emapper-locations\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003eclasspath:xml/*.xml\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e编写好 \u003ccode\u003eMapper\u003c/code\u003e 接口后，我们就需要定义 \u003ccode\u003eService\u003c/code\u003e 方法了：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public interface EmployeeService extends IService\u0026lt;Employee\u0026gt; {\n\n    List\u0026lt;Employee\u0026gt; listAllByLastName(String lastName);\n}\n\n@Service\npublic class EmployeeServiceImpl extends ServiceImpl\u0026lt;EmployeeMapper, Employee\u0026gt; implements EmployeeService {\n\n    @Override\n    public List\u0026lt;Employee\u0026gt; listAllByLastName(String lastName) {\n        return baseMapper.selectAllByLastName(lastName);\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeService\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eIService\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; {\n\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-en\"\u003elistAllByLastName\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e);\n}\n\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eService\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeServiceImpl\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eServiceImpl\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployeeMapper\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeService\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-en\"\u003elistAllByLastName\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e) {\n        \u003cspan class=\"pl-k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ebaseMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectAllByLastName\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e);\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e在 \u003ccode\u003eEmployeeServiceImpl\u003c/code\u003e 中我们无需将 \u003ccode\u003eEmployeeMapper\u003c/code\u003e 注入进来，而是使用 \u003ccode\u003eBaseMapper\u003c/code\u003e，查看 \u003ccode\u003eServiceImpl\u003c/code\u003e 的源码：\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/f17c6cadd4a15ae3a9b223b1f1266d260778bff354232cfcc0c8cecf5a48fa36/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313035313930383430333234392e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/f17c6cadd4a15ae3a9b223b1f1266d260778bff354232cfcc0c8cecf5a48fa36/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313035313930383430333234392e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/2021051908403249.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e可以看到它为我们注入了一个 \u003ccode\u003eBaseMapper\u003c/code\u003e 对象，而它是第一个泛型类型，也就是 \u003ccode\u003eEmployeeMapper\u003c/code\u003e 类型，所以我们可以直接使用这个 \u003ccode\u003ebaseMapper\u003c/code\u003e 来调用 \u003ccode\u003eMapper\u003c/code\u003e 中的方法，此时编写测试代码：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@SpringBootTest\n@MapperScan(\u0026quot;com.wwj.mybatisplusdemo.mapper\u0026quot;)\nclass MybatisplusDemoApplicationTests {\n\n    @Autowired\n    private EmployeeService employeeService;\n\n    @Test\n    void contextLoads() {\n        List\u0026lt;Employee\u0026gt; list = employeeService.listAllByLastName(\u0026quot;tom\u0026quot;);\n        list.forEach(System.out::println);\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSpringBootTest\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eMapperScan\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"com.wwj.mybatisplusdemo.mapper\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisplusDemoApplicationTests\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eAutowired\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeService\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e;\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n        \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003elistAllByLastName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"tom\"\u003c/span\u003e);\n        \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Employee(id=2, lastName=tom, email=tom@qq.com, age=30)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003etom\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eID 策略\u003c/h2\u003e\u003ca id=\"user-content-id-策略\" class=\"anchor\" aria-label=\"Permalink: ID 策略\" href=\"#id-策略\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e在创建表的时候我故意没有设置主键的增长策略，现在我们来插入一条数据，看看主键是如何增长的：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    Employee employee = new Employee();\n    employee.setLastName(\u0026quot;lisa\u0026quot;);\n    employee.setEmail(\u0026quot;lisa@qq.com\u0026quot;);\n    employee.setAge(20);\n    employeeService.save(employee);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetLastName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"lisa\"\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetEmail\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"lisa@qq.com\"\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetAge\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esave\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e插入成功后查询一下数据表：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"mysql\u0026gt; select * from tbl_employee;\n+---------------------+-----------+--------------+--------+------+\n| id                  | last_name | email        | gender | age  |\n+---------------------+-----------+--------------+--------+------+\n|                   1 | jack      | jack@qq.com  | 1      |   35 |\n|                   2 | tom       | tom@qq.com   | 1      |   30 |\n|                   3 | jerry     | jerry@qq.com | 1      |   40 |\n| 1385934720849584129 | lisa      | lisa@qq.com  | NULL   |   20 |\n+---------------------+-----------+--------------+--------+------+\n4 rows in set (0.00 sec)\"\u003e\u003cpre\u003emysql\u003cspan class=\"pl-k\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eselect\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e*\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e tbl_employee;\n\u003cspan class=\"pl-k\"\u003e+\u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e--\u003c/span\u003e-------------------+-----------+--------------+--------+------+\u003c/span\u003e\n| id                  | last_name | email        | gender | age  |\n\u003cspan class=\"pl-k\"\u003e+\u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e--\u003c/span\u003e-------------------+-----------+--------------+--------+------+\u003c/span\u003e\n|                   \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e | jack      | jack@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e  | \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e      |   \u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e |\n|                   \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e | tom       | tom@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e   | \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e      |   \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e |\n|                   \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e | jerry     | jerry@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e      |   \u003cspan class=\"pl-c1\"\u003e40\u003c/span\u003e |\n| \u003cspan class=\"pl-c1\"\u003e1385934720849584129\u003c/span\u003e | lisa      | lisa@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e  | \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e   |   \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e |\n\u003cspan class=\"pl-k\"\u003e+\u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e--\u003c/span\u003e-------------------+-----------+--------------+--------+------+\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e rows \u003cspan class=\"pl-k\"\u003ein\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eset\u003c/span\u003e (\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e sec)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e可以看到 id 是一串相当长的数字，这是什么意思呢？提前剧透一下，这其实是分布式 id，那又何为分布式 id 呢？\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e我们知道，对于一个大型应用，其访问量是非常巨大的，就比如说一个网站每天都有人进行注册，注册的用户信息就需要存入数据表，随着日子一天天过去，数据表中的用户越来越多，此时数据库的查询速度就会受到影响，所以一般情况下，当数据量足够庞大时，数据都会做分库分表的处理。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e然而，一旦分表，问题就产生了，很显然这些分表的数据都是属于同一张表的数据，只是因为数据量过大而分成若干张表，那么这几张表的主键 id 该怎么管理呢？每张表维护自己的 id？那数据将会有很多的 id 重复，这当然是不被允许的，其实，我们可以使用算法来生成一个绝对不会重复的 id，这样问题就迎刃而解了，事实上，分布式 id 的解决方案有很多：\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003eUUID\u003c/li\u003e\n\u003cli\u003eSnowFlake\u003c/li\u003e\n\u003cli\u003eTinyID\u003c/li\u003e\n\u003cli\u003eUidgenerator\u003c/li\u003e\n\u003cli\u003eLeaf\u003c/li\u003e\n\u003cli\u003eTinyid\u003c/li\u003e\n\u003cli\u003e......\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003e以 UUID 为例，它生成的是一串由数字和字母组成的字符串，显然并不适合作为数据表的 id，而且 id 保持递增有序会加快表的查询效率，基于此，\u003ccode\u003eMyBatisPlus\u003c/code\u003e 使用的就是 \u003ccode\u003eSnowFlake\u003c/code\u003e（雪花算法）。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eSnowflake\u003c/code\u003e 是 Twitter 开源的分布式 ID 生成算法。\u003ccode\u003eSnowflake\u003c/code\u003e 由 64 bit 的二进制数字组成，这 64bit 的二进制被分成了几部分，每一部分存储的数据都有特定的含义：\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003e第 0 位\u003c/strong\u003e： 符号位（标识正负），始终为 0，没有用，不用管。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e第 1~41 位\u003c/strong\u003e ：一共 41 位，用来表示时间戳，单位是毫秒，可以支撑 2 ^41 毫秒（约 69 年）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e第 42~52 位\u003c/strong\u003e ：一共 10 位，一般来说，前 5 位表示机房 ID，后 5 位表示机器 ID（实际项目中可以根据实际情况调整）。这样就可以区分不同集群/机房的节点。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e第 53~64 位\u003c/strong\u003e ：一共 12 位，用来表示序列号。 序列号为自增值，代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/f59400d2699d8d6e0c796743ccd5e8ad9f2b748a12c67d4667505e6a425a052f/68747470733a2f2f6f7363696d672e6f736368696e612e6e65742f6f73636e65742f75702d61376535346137376235616231643966613136643561653361336335306335616565392e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/f59400d2699d8d6e0c796743ccd5e8ad9f2b748a12c67d4667505e6a425a052f/68747470733a2f2f6f7363696d672e6f736368696e612e6e65742f6f73636e65742f75702d61376535346137376235616231643966613136643561653361336335306335616565392e706e67\" alt=\"\" data-canonical-src=\"https://oscimg.oschina.net/oscnet/up-a7e54a77b5ab1d9fa16d5ae3a3c50c5aee9.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e这也就是为什么插入数据后新的数据 id 是一长串数字的原因了，我们可以在实体类中使用 \u003ccode\u003e@TableId\u003c/code\u003e 来设置主键的策略：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\n@TableName(\u0026quot;tbl_employee\u0026quot;)\npublic class Employee {\n\n    @TableId(type = IdType.AUTO) // 设置主键策略\n    private Long id;\n    private String lastName;\n    private String email;\n    private Integer age;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"tbl_employee\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableId\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003etype\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eIdType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eAUTO\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e// 设置主键策略\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eMyBatisPlus\u003c/code\u003e 提供了几种主键的策略：\n\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/15859143f5966f7cb467c2cdadca0335437c1d8bcc4d9f8250544b170f799e3e/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343031313734352e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/15859143f5966f7cb467c2cdadca0335437c1d8bcc4d9f8250544b170f799e3e/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343031313734352e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210519084011745.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n其中 \u003ccode\u003eAUTO\u003c/code\u003e 表示数据库自增策略，该策略下需要数据库实现主键的自增（auto_increment)，\u003ccode\u003eASSIGN_ID\u003c/code\u003e 是雪花算法，默认使用的是该策略，\u003ccode\u003eASSIGN_UUID\u003c/code\u003e 是 UUID 策略，一般不会使用该策略。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e这里多说一点， 当实体类的主键名为 id，并且数据表的主键名也为 id 时，此时 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 会自动判定该属性为主键 id，倘若名字不是 id 时，就需要标注 \u003ccode\u003e@TableId\u003c/code\u003e 注解，若是实体类中主键名与数据表的主键名不一致，则可以进行声明：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@TableId(value = \u0026quot;uid\u0026quot;,type = IdType.AUTO) // 设置主键策略\nprivate Long id;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableId\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003evalue\u003c/span\u003e = \u003cspan class=\"pl-s\"\u003e\"uid\"\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003etype\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eIdType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eAUTO\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e// 设置主键策略\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e还可以在配置文件中配置全局的主键策略：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"mybatis-plus:\n  global-config:\n    db-config:\n      id-type: auto\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ent\"\u003emybatis-plus\u003c/span\u003e:\n  \u003cspan class=\"pl-ent\"\u003eglobal-config\u003c/span\u003e:\n    \u003cspan class=\"pl-ent\"\u003edb-config\u003c/span\u003e:\n      \u003cspan class=\"pl-ent\"\u003eid-type\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003eauto\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e这样能够避免在每个实体类中重复设置主键策略。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e属性自动填充\u003c/h2\u003e\u003ca id=\"user-content-属性自动填充\" class=\"anchor\" aria-label=\"Permalink: 属性自动填充\" href=\"#属性自动填充\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e翻阅《阿里巴巴Java开发手册》，在第 5 章 MySQL 数据库可以看到这样一条规范：\n\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/f5d2c2562996645cce44f85469c2644830592819ffa292bdc80ac8d1a837ea02/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231343832313338392e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/f5d2c2562996645cce44f85469c2644830592819ffa292bdc80ac8d1a837ea02/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231343832313338392e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210426214821389.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n对于一张数据表，它必须具备三个字段：\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eid\u003c/code\u003e : 唯一ID\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egmt_create\u003c/code\u003e : 保存的是当前数据创建的时间\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egmt_modified\u003c/code\u003e : 保存的是更新时间\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e我们改造一下数据表：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"alter table tbl_employee add column gmt_create datetime not null;\nalter table tbl_employee add column gmt_modified datetime not null;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003ealter\u003c/span\u003e \u003cspan class=\"pl-k\"\u003etable\u003c/span\u003e tbl_employee add column gmt_create datetime \u003cspan class=\"pl-k\"\u003enot null\u003c/span\u003e;\n\u003cspan class=\"pl-k\"\u003ealter\u003c/span\u003e \u003cspan class=\"pl-k\"\u003etable\u003c/span\u003e tbl_employee add column gmt_modified datetime \u003cspan class=\"pl-k\"\u003enot null\u003c/span\u003e;\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e然后改造一下实体类：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\n@TableName(\u0026quot;tbl_employee\u0026quot;)\npublic class Employee {\n\n    @TableId(type = IdType.AUTO) // 设置主键策略\n    private Long id;\n    private String lastName;\n    private String email;\n    private Integer age;\n    private LocalDateTime gmtCreate;\n    private LocalDateTime gmtModified;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"tbl_employee\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableId\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003etype\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eIdType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eAUTO\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e// 设置主键策略\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e此时我们在插入数据和更新数据的时候就需要手动去维护这两个属性：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    Employee employee = new Employee();\n    employee.setLastName(\u0026quot;lisa\u0026quot;);\n    employee.setEmail(\u0026quot;lisa@qq.com\u0026quot;);\n    employee.setAge(20);\n    // 设置创建时间\n    employee.setGmtCreate(LocalDateTime.now());\n    employee.setGmtModified(LocalDateTime.now());\n    employeeService.save(employee);\n}\n\n@Test\nvoid contextLoads() {\n    Employee employee = new Employee();\n    employee.setId(1385934720849584130L);\n    employee.setAge(50);\n    // 设置创建时间\n    employee.setGmtModified(LocalDateTime.now());\n    employeeService.updateById(employee);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetLastName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"lisa\"\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetEmail\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"lisa@qq.com\"\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetAge\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e);\n    \u003cspan class=\"pl-c\"\u003e// 设置创建时间\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetGmtCreate\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetGmtModified\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esave\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e);\n}\n\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetId\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1385934720849584130L\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetAge\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e50\u003c/span\u003e);\n    \u003cspan class=\"pl-c\"\u003e// 设置创建时间\u003c/span\u003e\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetGmtModified\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eupdateById\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e每次都需要维护这两个属性未免过于麻烦，好在 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 提供了字段自动填充功能来帮助我们进行管理，需要使用到的是 \u003ccode\u003e@TableField\u003c/code\u003e 注解：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\n@TableName(\u0026quot;tbl_employee\u0026quot;)\npublic class Employee {\n\n    @TableId(type = IdType.AUTO)\n    private Long id;\n    private String lastName;\n    private String email;\n    private Integer age;\n    @TableField(fill = FieldFill.INSERT) // 插入的时候自动填充\n    private LocalDateTime gmtCreate;\n    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新的时候自动填充\n    private LocalDateTime gmtModified;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"tbl_employee\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableId\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003etype\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eIdType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eAUTO\u003c/span\u003e)\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e;\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableField\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003efill\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eFieldFill\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eINSERT\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e// 插入的时候自动填充\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e;\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableField\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003efill\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eFieldFill\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eINSERT_UPDATE\u003c/span\u003e) \u003cspan class=\"pl-c\"\u003e// 插入和更新的时候自动填充\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e然后编写一个类实现 MetaObjectHandler 接口：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Component\n@Slf4j\npublic class MyMetaObjectHandler implements MetaObjectHandler {\n\n    /**\n     * 实现插入时的自动填充\n     * @param metaObject\n     */\n    @Override\n    public void insertFill(MetaObject metaObject) {\n        log.info(\u0026quot;insert开始属性填充\u0026quot;);\n        this.strictInsertFill(metaObject,\u0026quot;gmtCreate\u0026quot;, LocalDateTime.class,LocalDateTime.now());\n        this.strictInsertFill(metaObject,\u0026quot;gmtModified\u0026quot;, LocalDateTime.class,LocalDateTime.now());\n    }\n\n    /**\n     * 实现更新时的自动填充\n     * @param metaObject\n     */\n    @Override\n    public void updateFill(MetaObject metaObject) {\n        log.info(\u0026quot;update开始属性填充\u0026quot;);\n        this.strictInsertFill(metaObject,\u0026quot;gmtModified\u0026quot;, LocalDateTime.class,LocalDateTime.now());\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eComponent\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSlf4j\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMyMetaObjectHandler\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMetaObjectHandler\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c\"\u003e/**\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * 实现插入时的自动填充\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * @param metaObject\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     */\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003einsertFill\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eMetaObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e) {\n        \u003cspan class=\"pl-s1\"\u003elog\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003einfo\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"insert开始属性填充\"\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003estrictInsertFill\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\"gmtCreate\"\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e,\u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n        \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003estrictInsertFill\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e,\u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n    }\n\n    \u003cspan class=\"pl-c\"\u003e/**\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * 实现更新时的自动填充\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * @param metaObject\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     */\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eupdateFill\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eMetaObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e) {\n        \u003cspan class=\"pl-s1\"\u003elog\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003einfo\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"update开始属性填充\"\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003estrictInsertFill\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e,\u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e该接口中有两个未实现的方法，分别为插入和更新时的填充方法，在方法中调用 \u003ccode\u003estrictInsertFill()\u003c/code\u003e 方法 即可实现属性的填充，它需要四个参数：\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003emetaObject\u003c/code\u003e：元对象，就是方法的入参\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efieldName\u003c/code\u003e：为哪个属性进行自动填充\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efieldType\u003c/code\u003e：属性的类型\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efieldVal\u003c/code\u003e：需要填充的属性值\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003e此时在插入和更新数据之前，这两个方法会先被执行，以实现属性的自动填充，通过日志我们可以进行验证：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    Employee employee = new Employee();\n    employee.setId(1385934720849584130L);\n    employee.setAge(15);\n    employeeService.updateById(employee);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetId\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1385934720849584130L\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetAge\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e15\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eupdateById\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eemployee\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"INFO 15584 --- [           main] c.w.m.handler.MyMetaObjectHandler        : update开始属性填充\n2021-04-24 21:32:19.788  INFO 15584 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...\n2021-04-24 21:32:21.244  INFO 15584 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003eINFO\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e15584\u003c/span\u003e ---\u003cspan class=\"pl-s1\"\u003e\u003c/span\u003e [           \u003cspan class=\"pl-s1\"\u003emain\u003c/span\u003e] \u003cspan class=\"pl-s1\"\u003ec\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ew\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003em\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ehandler\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eMyMetaObjectHandler\u003c/span\u003e        : \u003cspan class=\"pl-s1\"\u003eupdate开始属性填充\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e32\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e19.788\u003c/span\u003e  \u003cspan class=\"pl-c1\"\u003eINFO\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e15584\u003c/span\u003e ---\u003cspan class=\"pl-s1\"\u003e\u003c/span\u003e [           \u003cspan class=\"pl-s1\"\u003emain\u003c/span\u003e] \u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ezaxxer\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ehikari\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eHikariDataSource\u003c/span\u003e       : \u003cspan class=\"pl-s1\"\u003eHikariPool\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e - \u003cspan class=\"pl-s1\"\u003eStarting\u003c/span\u003e...\n\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e32\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e21.244\u003c/span\u003e  \u003cspan class=\"pl-c1\"\u003eINFO\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e15584\u003c/span\u003e ---\u003cspan class=\"pl-s1\"\u003e\u003c/span\u003e [           \u003cspan class=\"pl-s1\"\u003emain\u003c/span\u003e] \u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ezaxxer\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ehikari\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eHikariDataSource\u003c/span\u003e       : \u003cspan class=\"pl-s1\"\u003eHikariPool\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e - \u003cspan class=\"pl-smi\"\u003eStart\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ecompleted\u003c/span\u003e.\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e属性填充其实可以进行一些优化，考虑一些特殊情况，对于一些不存在的属性，就不需要进行属性填充，对于一些设置了值的属性，也不需要进行属性填充，这样可以提高程序的整体运行效率：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Component\n@Slf4j\npublic class MyMetaObjectHandler implements MetaObjectHandler {\n\n    @Override\n    public void insertFill(MetaObject metaObject) {\n        boolean hasGmtCreate = metaObject.hasSetter(\u0026quot;gmtCreate\u0026quot;);\n        boolean hasGmtModified = metaObject.hasSetter(\u0026quot;gmtModified\u0026quot;);\n        if (hasGmtCreate) {\n            Object gmtCreate = this.getFieldValByName(\u0026quot;gmtCreate\u0026quot;, metaObject);\n            if (gmtCreate == null) {\n                this.strictInsertFill(metaObject, \u0026quot;gmtCreate\u0026quot;, LocalDateTime.class, LocalDateTime.now());\n            }\n        }\n        if (hasGmtModified) {\n            Object gmtModified = this.getFieldValByName(\u0026quot;gmtModified\u0026quot;, metaObject);\n            if (gmtModified == null) {\n                this.strictInsertFill(metaObject, \u0026quot;gmtModified\u0026quot;, LocalDateTime.class, LocalDateTime.now());\n            }\n        }\n    }\n\n    @Override\n    public void updateFill(MetaObject metaObject) {\n        boolean hasGmtModified = metaObject.hasSetter(\u0026quot;gmtModified\u0026quot;);\n        if (hasGmtModified) {\n            Object gmtModified = this.getFieldValByName(\u0026quot;gmtModified\u0026quot;, metaObject);\n            if (gmtModified == null) {\n                this.strictInsertFill(metaObject, \u0026quot;gmtModified\u0026quot;, LocalDateTime.class, LocalDateTime.now());\n            }\n        }\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eComponent\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSlf4j\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMyMetaObjectHandler\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eimplements\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMetaObjectHandler\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003einsertFill\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eMetaObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e) {\n        \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ehasGmtCreate\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003ehasSetter\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gmtCreate\"\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ehasGmtModified\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003ehasSetter\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e);\n        \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003ehasGmtCreate\u003c/span\u003e) {\n            \u003cspan class=\"pl-smi\"\u003eObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetFieldValByName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gmtCreate\"\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e);\n            \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e == \u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e) {\n                \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003estrictInsertFill\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"gmtCreate\"\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n            }\n        }\n        \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003ehasGmtModified\u003c/span\u003e) {\n            \u003cspan class=\"pl-smi\"\u003eObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetFieldValByName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e);\n            \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e == \u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e) {\n                \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003estrictInsertFill\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n            }\n        }\n    }\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eOverride\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eupdateFill\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eMetaObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e) {\n        \u003cspan class=\"pl-smi\"\u003eboolean\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ehasGmtModified\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003ehasSetter\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e);\n        \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003ehasGmtModified\u003c/span\u003e) {\n            \u003cspan class=\"pl-smi\"\u003eObject\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetFieldValByName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e);\n            \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e == \u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e) {\n                \u003cspan class=\"pl-smi\"\u003ethis\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003estrictInsertFill\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003emetaObject\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"gmtModified\"\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e, \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003enow\u003c/span\u003e());\n            }\n        }\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e逻辑删除\u003c/h2\u003e\u003ca id=\"user-content-逻辑删除\" class=\"anchor\" aria-label=\"Permalink: 逻辑删除\" href=\"#逻辑删除\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e逻辑删除对应的是物理删除，分别介绍一下这两个概念：\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003e物理删除\u003c/strong\u003e ：指的是真正的删除，即：当执行删除操作时，将数据表中的数据进行删除，之后将无法再查询到该数据\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e逻辑删除\u003c/strong\u003e ：并不是真正意义上的删除，只是对于用户不可见了，它仍然存在与数据表中\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003e在这个数据为王的时代，数据就是财富，所以一般并不会有哪个系统在删除某些重要数据时真正删掉了数据，通常都是在数据库中建立一个状态列，让其默认为 0，当为 0 时，用户可见；当执行了删除操作，就将状态列改为 1，此时用户不可见，但数据还是在表中的。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/1a6f590c2b990911ba84c0ef9038887a454e831c17a607e496e2bb355ec3b46f/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231353130373231302e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/1a6f590c2b990911ba84c0ef9038887a454e831c17a607e496e2bb355ec3b46f/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231353130373231302e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210426215107210.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e按照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议，我们来为数据表新增一个\u003ccode\u003eis_deleted\u003c/code\u003e 字段：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"alter table tbl_employee add column is_deleted tinyint not null;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003ealter\u003c/span\u003e \u003cspan class=\"pl-k\"\u003etable\u003c/span\u003e tbl_employee add column is_deleted tinyint \u003cspan class=\"pl-k\"\u003enot null\u003c/span\u003e;\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e在实体类中也要添加这一属性：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\n@TableName(\u0026quot;tbl_employee\u0026quot;)\npublic class Employee {\n\n    @TableId(type = IdType.AUTO)\n    private Long id;\n    private String lastName;\n    private String email;\n    private Integer age;\n    @TableField(fill = FieldFill.INSERT)\n    private LocalDateTime gmtCreate;\n    @TableField(fill = FieldFill.INSERT_UPDATE)\n    private LocalDateTime gmtModified;\n    /**\n     * 逻辑删除属性\n     */\n    @TableLogic\n    @TableField(\u0026quot;is_deleted\u0026quot;)\n    private Boolean deleted;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableName\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"tbl_employee\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableId\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003etype\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eIdType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eAUTO\u003c/span\u003e)\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e;\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableField\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003efill\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eFieldFill\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eINSERT\u003c/span\u003e)\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e;\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableField\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003efill\u003c/span\u003e = \u003cspan class=\"pl-smi\"\u003eFieldFill\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eINSERT_UPDATE\u003c/span\u003e)\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLocalDateTime\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e;\n    \u003cspan class=\"pl-c\"\u003e/**\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * 逻辑删除属性\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     */\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableLogic\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTableField\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"is_deleted\"\u003c/span\u003e)\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eBoolean\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/243c18c226a2e34b57bcca15fcfc1984321776c156ae36338aac4fa77cc91030/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313034323632313533303136322e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/243c18c226a2e34b57bcca15fcfc1984321776c156ae36338aac4fa77cc91030/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313034323632313533303136322e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/2021042621530162.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e还是参照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议，对于布尔类型变量，不能加 is 前缀，所以我们的属性被命名为 \u003ccode\u003edeleted\u003c/code\u003e，但此时就无法与数据表的字段进行对应了，所以我们需要使用 \u003ccode\u003e@TableField\u003c/code\u003e 注解来声明一下数据表的字段名，而 \u003ccode\u003e@TableLogin\u003c/code\u003e 注解用于设置逻辑删除属性；此时我们执行删除操作：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    employeeService.removeById(3);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eremoveById\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e查询数据表：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"mysql\u0026gt; select * from tbl_employee;\n+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+\n| id                  | last_name | email        | gender | age  | gmt_create          | gmt_modified        | is_deleted |\n+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+\n|                   1 | jack      | jack@qq.com  | 1      |   35 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |\n|                   2 | tom       | tom@qq.com   | 1      |   30 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |\n|                   3 | jerry     | jerry@qq.com | 1      |   40 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          1 |\n| 1385934720849584129 | lisa      | lisa@qq.com  | NULL   |   20 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |\n| 1385934720849584130 | lisa      | lisa@qq.com  | NULL   |   15 | 2021-04-24 21:14:18 | 2021-04-24 21:32:19 |          0 |\n+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+\n5 rows in set (0.00 sec)\"\u003e\u003cpre\u003emysql\u003cspan class=\"pl-k\"\u003e\u0026gt;\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eselect\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e*\u003c/span\u003e \u003cspan class=\"pl-k\"\u003efrom\u003c/span\u003e tbl_employee;\n\u003cspan class=\"pl-k\"\u003e+\u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e--\u003c/span\u003e-------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+\u003c/span\u003e\n| id                  | last_name | email        | gender | age  | gmt_create          | gmt_modified        | is_deleted |\n\u003cspan class=\"pl-k\"\u003e+\u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e--\u003c/span\u003e-------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+\u003c/span\u003e\n|                   \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e | jack      | jack@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e  | \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e      |   \u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e |          \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e |\n|                   \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e | tom       | tom@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e   | \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e      |   \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e |          \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e |\n|                   \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e | jerry     | jerry@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e      |   \u003cspan class=\"pl-c1\"\u003e40\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e |          \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e |\n| \u003cspan class=\"pl-c1\"\u003e1385934720849584129\u003c/span\u003e | lisa      | lisa@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e  | \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e   |   \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e0000\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e |          \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e |\n| \u003cspan class=\"pl-c1\"\u003e1385934720849584130\u003c/span\u003e | lisa      | lisa@\u003cspan class=\"pl-c1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003ecom\u003c/span\u003e  | \u003cspan class=\"pl-k\"\u003eNULL\u003c/span\u003e   |   \u003cspan class=\"pl-c1\"\u003e15\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e | \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e\u003cspan class=\"pl-k\"\u003e-\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e32\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e19\u003c/span\u003e |          \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e |\n\u003cspan class=\"pl-k\"\u003e+\u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e--\u003c/span\u003e-------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e5\u003c/span\u003e rows \u003cspan class=\"pl-k\"\u003ein\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eset\u003c/span\u003e (\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003e00\u003c/span\u003e sec)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e可以看到数据并没有被删除，只是 \u003ccode\u003eis_deleted\u003c/code\u003e 字段的属性值被更新成了 1，此时我们再来执行查询操作：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    List\u0026lt;Employee\u0026gt; list = employeeService.list();\n    list.forEach(System.out::println);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003elist\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e执行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)\nEmployee(id=2, lastName=tom, email=tom@qq.com, age=30, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)\nEmployee(id=1385934720849584129, lastName=lisa, email=lisa@qq.com, age=20, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)\nEmployee(id=1385934720849584130, lastName=lisa, email=lisa@qq.com, age=15, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:32:19, deleted=false)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejack\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003efalse\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003etom\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003efalse\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1385934720849584129\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003elisa\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003elisa\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003efalse\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1385934720849584130\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003elisa\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003elisa\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e15\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e32\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e19\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003efalse\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e会发现第三条数据并没有被查询出来，它是如何实现的呢？我们可以输出 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 生成的 SQL 来分析一下，在配置文件中进行配置：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"mybatis-plus:\n  configuration:\n    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出SQL日志\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ent\"\u003emybatis-plus\u003c/span\u003e:\n  \u003cspan class=\"pl-ent\"\u003econfiguration\u003c/span\u003e:\n    \u003cspan class=\"pl-ent\"\u003elog-impl\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003eorg.apache.ibatis.logging.stdout.StdOutImpl \u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e 输出SQL日志\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"==\u0026gt;  Preparing: SELECT id,last_name,email,age,gmt_create,gmt_modified,is_deleted AS deleted FROM tbl_employee WHERE is_deleted=0\n==\u0026gt; Parameters:\n\u0026lt;==    Columns: id, last_name, email, age, gmt_create, gmt_modified, deleted\n\u0026lt;==        Row: 1, jack, jack@qq.com, 35, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0\n\u0026lt;==        Row: 2, tom, tom@qq.com, 30, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0\n\u0026lt;==        Row: 1385934720849584129, lisa, lisa@qq.com, 20, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0\n\u0026lt;==        Row: 1385934720849584130, lisa, lisa@qq.com, 15, 2021-04-24 21:14:18, 2021-04-24 21:32:19, 0\n\u0026lt;==      Total: 4\"\u003e\u003cpre\u003e==\u0026gt;  \u003cspan class=\"pl-s1\"\u003ePreparing\u003c/span\u003e: \u003cspan class=\"pl-smi\"\u003eSELECT\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003elast_name\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003egmt_create\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003egmt_modified\u003c/span\u003e,\u003cspan class=\"pl-s1\"\u003eis_deleted\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eAS\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eFROM\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003etbl_employee\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eWHERE\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eis_deleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\n==\u0026gt; \u003cspan class=\"pl-s1\"\u003eParameters\u003c/span\u003e:\n\u0026lt;==    \u003cspan class=\"pl-s1\"\u003eColumns\u003c/span\u003e: \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elast_name\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmt_create\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmt_modified\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e\n\u0026lt;==        \u003cspan class=\"pl-s1\"\u003eRow\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\n\u0026lt;==        \u003cspan class=\"pl-s1\"\u003eRow\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\n\u0026lt;==        \u003cspan class=\"pl-s1\"\u003eRow\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e1385934720849584129\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elisa\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elisa\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\n\u0026lt;==        \u003cspan class=\"pl-s1\"\u003eRow\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e1385934720849584130\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elisa\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elisa\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e15\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e \u003cspan class=\"pl-c1\"\u003e21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e32\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e19\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e\n\u0026lt;==      \u003cspan class=\"pl-s1\"\u003eTotal\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e原来它在查询时携带了一个条件： \u003ccode\u003eis_deleted=0\u003c/code\u003e ，这也说明了 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 默认 0 为不删除，1 为删除。\n若是你想修改这个规定，比如设置-1 为删除，1 为不删除，也可以进行配置：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"mybatis-plus:\n  global-config:\n    db-config:\n      id-type: auto\n      logic-delete-field: deleted # 逻辑删除属性名\n      logic-delete-value: -1 # 删除值\n      logic-not-delete-value: 1 # 不删除值\"\u003e\u003cpre\u003e\u003cspan class=\"pl-ent\"\u003emybatis-plus\u003c/span\u003e:\n  \u003cspan class=\"pl-ent\"\u003eglobal-config\u003c/span\u003e:\n    \u003cspan class=\"pl-ent\"\u003edb-config\u003c/span\u003e:\n      \u003cspan class=\"pl-ent\"\u003eid-type\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003eauto\u003c/span\u003e\n      \u003cspan class=\"pl-ent\"\u003elogic-delete-field\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003edeleted \u003c/span\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e 逻辑删除属性名\u003c/span\u003e\n      \u003cspan class=\"pl-ent\"\u003elogic-delete-value\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e-1\u003c/span\u003e \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e 删除值\u003c/span\u003e\n      \u003cspan class=\"pl-ent\"\u003elogic-not-delete-value\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e 不删除值\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e但建议使用默认的配置，阿里巴巴开发手册也规定 1 表示删除，0 表示未删除。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e分页插件\u003c/h2\u003e\u003ca id=\"user-content-分页插件\" class=\"anchor\" aria-label=\"Permalink: 分页插件\" href=\"#分页插件\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e对于分页功能，\u003ccode\u003eMyBatisPlus\u003c/code\u003e 提供了分页插件，只需要进行简单的配置即可实现：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Configuration\npublic class MyBatisConfig {\n\n    /**\n     * 注册分页插件\n     * @return\n     */\n    @Bean\n    public MybatisPlusInterceptor mybatisPlusInterceptor() {\n        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();\n        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));\n        return interceptor;\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eConfiguration\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMyBatisConfig\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c\"\u003e/**\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * 注册分页插件\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * @return\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     */\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eBean\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisPlusInterceptor\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emybatisPlusInterceptor\u003c/span\u003e() {\n        \u003cspan class=\"pl-smi\"\u003eMybatisPlusInterceptor\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisPlusInterceptor\u003c/span\u003e();\n        \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eaddInnerInterceptor\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ePaginationInnerInterceptor\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDbType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eMYSQL\u003c/span\u003e));\n        \u003cspan class=\"pl-k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e;\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e接下来我们就可以使用分页插件提供的功能了：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    Page\u0026lt;Employee\u0026gt; page = new Page\u0026lt;\u0026gt;(1,2);\n    employeeService.page(page, null);\n    List\u0026lt;Employee\u0026gt; employeeList = page.getRecords();\n    employeeList.forEach(System.out::println);\n    System.out.println(\u0026quot;获取总条数:\u0026quot; + page.getTotal());\n    System.out.println(\u0026quot;获取当前页码:\u0026quot; + page.getCurrent());\n    System.out.println(\u0026quot;获取总页码:\u0026quot; + page.getPages());\n    System.out.println(\u0026quot;获取每页显示的数据条数:\u0026quot; + page.getSize());\n    System.out.println(\u0026quot;是否有上一页:\u0026quot; + page.hasPrevious());\n    System.out.println(\u0026quot;是否有下一页:\u0026quot; + page.hasNext());\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003ePage\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ePage\u003c/span\u003e\u0026lt;\u0026gt;(\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e,\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003epage\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e);\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003eemployeeList\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetRecords\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003eemployeeList\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n    \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"获取总条数:\"\u003c/span\u003e + \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetTotal\u003c/span\u003e());\n    \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"获取当前页码:\"\u003c/span\u003e + \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetCurrent\u003c/span\u003e());\n    \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"获取总页码:\"\u003c/span\u003e + \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetPages\u003c/span\u003e());\n    \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"获取每页显示的数据条数:\"\u003c/span\u003e + \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetSize\u003c/span\u003e());\n    \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"是否有上一页:\"\u003c/span\u003e + \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003ehasPrevious\u003c/span\u003e());\n    \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"是否有下一页:\"\u003c/span\u003e + \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003ehasNext\u003c/span\u003e());\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e其中的 \u003ccode\u003ePage\u003c/code\u003e 对象用于指定分页查询的规则，这里表示按每页两条数据进行分页，并查询第一页的内容，运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)\nEmployee(id=2, lastName=tom, email=tom@qq.com, age=30, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)\n获取总条数:4\n获取当前页码:1\n获取总页码:2\n获取每页显示的数据条数:2\n是否有上一页:false\n是否有下一页:true\"\u003e\u003cpre\u003e\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejack\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e)\n\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003etom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003etom\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e)\n\u003cspan class=\"pl-s1\"\u003e获取总条数\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e4\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003e获取当前页码\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003e获取总页码\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003e获取每页显示的数据条数\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003e是否有上一页\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003efalse\u003c/span\u003e\n\u003cspan class=\"pl-s1\"\u003e是否有下一页\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e倘若在分页过程中需要限定一些条件，我们就需要构建 QueryWrapper 来实现：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    Page\u0026lt;Employee\u0026gt; page = new Page\u0026lt;\u0026gt;(1, 2);\n    employeeService.page(page, new QueryWrapper\u0026lt;Employee\u0026gt;()\n                         .between(\u0026quot;age\u0026quot;, 20, 50)\n                         .eq(\u0026quot;gender\u0026quot;, 1));\n    List\u0026lt;Employee\u0026gt; employeeList = page.getRecords();\n    employeeList.forEach(System.out::println);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003ePage\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ePage\u003c/span\u003e\u0026lt;\u0026gt;(\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployeeService\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003epage\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e, \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eQueryWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt;()\n                         .\u003cspan class=\"pl-en\"\u003ebetween\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"age\"\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e50\u003c/span\u003e)\n                         .\u003cspan class=\"pl-en\"\u003eeq\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"gender\"\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e));\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003eemployeeList\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003epage\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egetRecords\u003c/span\u003e();\n    \u003cspan class=\"pl-s1\"\u003eemployeeList\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e此时分页的数据就应该是年龄在 20~50 岁之间，且 gender 值为 1 的员工信息，然后再对这些数据进行分页。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e乐观锁\u003c/h2\u003e\u003ca id=\"user-content-乐观锁\" class=\"anchor\" aria-label=\"Permalink: 乐观锁\" href=\"#乐观锁\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e当程序中出现并发访问时，就需要保证数据的一致性。以商品系统为例，现在有两个管理员均想对同一件售价为 100 元的商品进行修改，A 管理员正准备将商品售价改为 150 元，但此时出现了网络问题，导致 A 管理员的操作陷入了等待状态；此时 B 管理员也进行修改，将商品售价改为了 200 元，修改完成后 B 管理员退出了系统，此时 A 管理员的操作也生效了，这样便使得 A 管理员的操作直接覆盖了 B 管理员的操作，B 管理员后续再进行查询时会发现商品售价变为了 150 元，这样的情况是绝对不允许发生的。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e要想解决这一问题，可以给数据表加锁，常见的方式有两种：\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e乐观锁\u003c/li\u003e\n\u003cli\u003e悲观锁\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003e悲观锁认为并发情况一定会发生，所以在某条数据被修改时，为了避免其它人修改，会直接对数据表进行加锁，它依靠的是数据库本身提供的锁机制（表锁、行锁、读锁、写锁）。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e而乐观锁则相反，它认为数据产生冲突的情况一般不会发生，所以在修改数据的时候并不会对数据表进行加锁的操作，而是在提交数据时进行校验，判断提交上来的数据是否会发生冲突，如果发生冲突，则提示用户重新进行操作，一般的实现方式为 \u003ccode\u003e设置版本号字段\u003c/code\u003e 。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e就以商品售价为例，在该表中设置一个版本号字段，让其初始为 1，此时 A 管理员和 B 管理员同时需要修改售价，它们会先读取到数据表中的内容，此时两个管理员读取到的版本号都为 1，此时 B 管理员的操作先生效了，它就会将当前数据表中对应数据的版本号与最开始读取到的版本号作一个比对，发现没有变化，于是修改就生效了，此时版本号加 1。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e而 A 管理员马上也提交了修改操作，但是此时的版本号为 2，与最开始读取到的版本号并不对应，这就说明数据发生了冲突，此时应该提示 A 管理员操作失败，并让 A 管理员重新查询一次数据。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/edba75d690913bdb285f478e808d9b4cac7cbb889c9ff638564ee1e0d272b25d/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363232313430383632332e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/edba75d690913bdb285f478e808d9b4cac7cbb889c9ff638564ee1e0d272b25d/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363232313430383632332e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210426221408623.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e乐观锁的优势在于采取了更加宽松的加锁机制，能够提高程序的吞吐量，适用于读操作多的场景。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e那么接下来我们就来模拟这一过程。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e1.创建一张新的数据表：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"create table shop(\n\tid bigint(20) not null auto_increment,\n  name varchar(30) not null,\n  price int(11) default 0,\n  version int(11) default 1,\n  primary key(id)\n);\n\ninsert into shop(id,name,price) values(1,'笔记本电脑',8000);\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003ecreate\u003c/span\u003e \u003cspan class=\"pl-k\"\u003etable\u003c/span\u003e \u003cspan class=\"pl-en\"\u003eshop\u003c/span\u003e(\n\tid \u003cspan class=\"pl-k\"\u003ebigint\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e) \u003cspan class=\"pl-k\"\u003enot null\u003c/span\u003e auto_increment,\n  name \u003cspan class=\"pl-k\"\u003evarchar\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e30\u003c/span\u003e) \u003cspan class=\"pl-k\"\u003enot null\u003c/span\u003e,\n  price \u003cspan class=\"pl-k\"\u003eint\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e) default \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e,\n  version \u003cspan class=\"pl-k\"\u003eint\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e11\u003c/span\u003e) default \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e,\n  \u003cspan class=\"pl-k\"\u003eprimary key\u003c/span\u003e(id)\n);\n\n\u003cspan class=\"pl-k\"\u003einsert into\u003c/span\u003e shop(id,name,price) \u003cspan class=\"pl-k\"\u003evalues\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e笔记本电脑\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e,\u003cspan class=\"pl-c1\"\u003e8000\u003c/span\u003e);\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e2.创建实体类：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\npublic class Shop {\n\n    private Long id;\n    private String name;\n    private Integer price;\n    private Integer version;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eShop\u003c/span\u003e {\n\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ename\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eprice\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eversion\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e3.创建对应的 \u003ccode\u003eMapper\u003c/code\u003e 接口：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"public interface ShopMapper extends BaseMapper\u0026lt;Shop\u0026gt; {\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003einterface\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eShopMapper\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eextends\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eBaseMapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eShop\u003c/span\u003e\u0026gt; {\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e4.编写测试代码：\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@SpringBootTest\n@MapperScan(\u0026quot;com.wwj.mybatisplusdemo.mapper\u0026quot;)\nclass MybatisplusDemoApplicationTests {\n\n    @Autowired\n    private ShopMapper shopMapper;\n\n    /**\n     * 模拟并发场景\n     */\n    @Test\n    void contextLoads() {\n        // A、B管理员读取数据\n        Shop A = shopMapper.selectById(1L);\n        Shop B = shopMapper.selectById(1L);\n        // B管理员先修改\n        B.setPrice(9000);\n        int result = shopMapper.updateById(B);\n        if (result == 1) {\n            System.out.println(\u0026quot;B管理员修改成功!\u0026quot;);\n        } else {\n            System.out.println(\u0026quot;B管理员修改失败!\u0026quot;);\n        }\n        // A管理员后修改\n        A.setPrice(8500);\n        int result2 = shopMapper.updateById(A);\n        if (result2 == 1) {\n            System.out.println(\u0026quot;A管理员修改成功!\u0026quot;);\n        } else {\n            System.out.println(\u0026quot;A管理员修改失败!\u0026quot;);\n        }\n        // 最后查询\n        System.out.println(shopMapper.selectById(1L));\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSpringBootTest\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eMapperScan\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"com.wwj.mybatisplusdemo.mapper\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisplusDemoApplicationTests\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eAutowired\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eShopMapper\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eshopMapper\u003c/span\u003e;\n\n    \u003cspan class=\"pl-c\"\u003e/**\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * 模拟并发场景\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     */\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n        \u003cspan class=\"pl-c\"\u003e// A、B管理员读取数据\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eShop\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eA\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eshopMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectById\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1L\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003eShop\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eB\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eshopMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectById\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1L\u003c/span\u003e);\n        \u003cspan class=\"pl-c\"\u003e// B管理员先修改\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eB\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetPrice\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e9000\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eshopMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eupdateById\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eB\u003c/span\u003e);\n        \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003eresult\u003c/span\u003e == \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e) {\n            \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"B管理员修改成功!\"\u003c/span\u003e);\n        } \u003cspan class=\"pl-k\"\u003eelse\u003c/span\u003e {\n            \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"B管理员修改失败!\"\u003c/span\u003e);\n        }\n        \u003cspan class=\"pl-c\"\u003e// A管理员后修改\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eA\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003esetPrice\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e8500\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003eint\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eresult2\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eshopMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eupdateById\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eA\u003c/span\u003e);\n        \u003cspan class=\"pl-k\"\u003eif\u003c/span\u003e (\u003cspan class=\"pl-s1\"\u003eresult2\u003c/span\u003e == \u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e) {\n            \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"A管理员修改成功!\"\u003c/span\u003e);\n        } \u003cspan class=\"pl-k\"\u003eelse\u003c/span\u003e {\n            \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"A管理员修改失败!\"\u003c/span\u003e);\n        }\n        \u003cspan class=\"pl-c\"\u003e// 最后查询\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eprintln\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eshopMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectById\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003e1L\u003c/span\u003e));\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e执行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"B管理员修改成功!\nA管理员修改成功!\nShop(id=1, name=笔记本电脑, price=8500, version=1)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eB管理员修改成功\u003c/span\u003e!\n\u003cspan class=\"pl-s1\"\u003eA管理员修改成功\u003c/span\u003e!\n\u003cspan class=\"pl-en\"\u003eShop\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ename\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003e笔记本电脑\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eprice\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e8500\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eversion\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003e问题出现了，B 管理员的操作被 A 管理员覆盖，那么该如何解决这一问题呢？\u003c/strong\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e其实 \u003ccode\u003eMyBatisPlus\u003c/code\u003e 已经提供了乐观锁机制，只需要在实体类中使用 \u003ccode\u003e@Version\u003c/code\u003e 声明版本号属性：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Data\npublic class Shop {\n\n    private Long id;\n    private String name;\n    private Integer price;\n    @Version // 声明版本号属性\n    private Integer version;\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eData\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eShop\u003c/span\u003e {\n\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLong\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eString\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003ename\u003c/span\u003e;\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eprice\u003c/span\u003e;\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eVersion\u003c/span\u003e \u003cspan class=\"pl-c\"\u003e// 声明版本号属性\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eInteger\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eversion\u003c/span\u003e;\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e然后注册乐观锁插件：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Configuration\npublic class MyBatisConfig {\n\n    /**\n     * 注册插件\n     * @return\n     */\n    @Bean\n    public MybatisPlusInterceptor mybatisPlusInterceptor() {\n        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();\n        // 分页插件\n        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));\n        // 乐观锁插件\n        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());\n        return interceptor;\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eConfiguration\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMyBatisConfig\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c\"\u003e/**\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * 注册插件\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     * @return\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e     */\u003c/span\u003e\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eBean\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003epublic\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisPlusInterceptor\u003c/span\u003e \u003cspan class=\"pl-en\"\u003emybatisPlusInterceptor\u003c/span\u003e() {\n        \u003cspan class=\"pl-smi\"\u003eMybatisPlusInterceptor\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisPlusInterceptor\u003c/span\u003e();\n        \u003cspan class=\"pl-c\"\u003e// 分页插件\u003c/span\u003e\n        \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eaddInnerInterceptor\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003ePaginationInnerInterceptor\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eDbType\u003c/span\u003e.\u003cspan class=\"pl-c1\"\u003eMYSQL\u003c/span\u003e));\n        \u003cspan class=\"pl-c\"\u003e// 乐观锁插件\u003c/span\u003e\n        \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eaddInnerInterceptor\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eOptimisticLockerInnerInterceptor\u003c/span\u003e());\n        \u003cspan class=\"pl-k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003einterceptor\u003c/span\u003e;\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e重新执行测试代码，结果如下：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"B管理员修改成功!\nA管理员修改失败!\nShop(id=1, name=笔记本电脑, price=9000, version=2)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-smi\"\u003eB管理员修改成功\u003c/span\u003e!\n\u003cspan class=\"pl-s1\"\u003eA管理员修改失败\u003c/span\u003e!\n\u003cspan class=\"pl-en\"\u003eShop\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ename\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003e笔记本电脑\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eprice\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e9000\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eversion\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e此时 A 管理员的修改就失败了，它需要重新读取最新的数据才能再次进行修改。\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e条件构造器\u003c/h2\u003e\u003ca id=\"user-content-条件构造器\" class=\"anchor\" aria-label=\"Permalink: 条件构造器\" href=\"#条件构造器\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e在分页插件中我们简单地使用了一下条件构造器（\u003ccode\u003eWrapper\u003c/code\u003e），下面我们来详细了解一下。\n先来看看 \u003ccode\u003eWrapper\u003c/code\u003e 的继承体系：\n\u003ca target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://camo.githubusercontent.com/974e52001f5f92df99b0987a16491b732a615f8c076758a0f63d67df88caf469/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038333934343331352e706e67\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/974e52001f5f92df99b0987a16491b732a615f8c076758a0f63d67df88caf469/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038333934343331352e706e67\" alt=\"\" data-canonical-src=\"https://img-blog.csdnimg.cn/20210519083944315.png\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n分别介绍一下它们的作用：\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eWrapper\u003c/code\u003e：条件构造器抽象类，最顶端的父类\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eAbstractWrapper\u003c/code\u003e：查询条件封装抽象类，生成 SQL 的 where 条件\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eQueryWrapper\u003c/code\u003e：用于对象封装\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eUpdateWrapper\u003c/code\u003e：用于条件封装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAbstractLambdaWrapper\u003c/code\u003e：Lambda 语法使用 Wrapper\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eLambdaQueryWrapper\u003c/code\u003e：用于对象封装，使用 Lambda 语法\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eLambdaUpdateWrapper\u003c/code\u003e：用于条件封装，使用 Lambda 语法\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003e通常我们使用的都是 \u003ccode\u003eQueryWrapper\u003c/code\u003e 和 \u003ccode\u003eUpdateWrapper\u003c/code\u003e，若是想使用 Lambda 语法来编写，也可以使用 \u003ccode\u003eLambdaQueryWrapper\u003c/code\u003e 和 \u003ccode\u003eLambdaUpdateWrapper\u003c/code\u003e，通过这些条件构造器，我们能够很方便地来实现一些复杂的筛选操作，比如：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@SpringBootTest\n@MapperScan(\u0026quot;com.wwj.mybatisplusdemo.mapper\u0026quot;)\nclass MybatisplusDemoApplicationTests {\n\n    @Autowired\n    private EmployeeMapper employeeMapper;\n\n    @Test\n    void contextLoads() {\n        // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息\n        QueryWrapper\u0026lt;Employee\u0026gt; wrapper = new QueryWrapper\u0026lt;\u0026gt;();\n        wrapper.like(\u0026quot;last_name\u0026quot;, \u0026quot;j\u0026quot;);\n        wrapper.gt(\u0026quot;age\u0026quot;, 20);\n        wrapper.isNotNull(\u0026quot;email\u0026quot;);\n        List\u0026lt;Employee\u0026gt; list = employeeMapper.selectList(wrapper);\n        list.forEach(System.out::println);\n    }\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eSpringBootTest\u003c/span\u003e\n\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eMapperScan\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"com.wwj.mybatisplusdemo.mapper\"\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003eclass\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eMybatisplusDemoApplicationTests\u003c/span\u003e {\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eAutowired\u003c/span\u003e\n    \u003cspan class=\"pl-k\"\u003eprivate\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eEmployeeMapper\u003c/span\u003e \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e;\n\n    \u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n        \u003cspan class=\"pl-c\"\u003e// 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息\u003c/span\u003e\n        \u003cspan class=\"pl-smi\"\u003eQueryWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eQueryWrapper\u003c/span\u003e\u0026lt;\u0026gt;();\n        \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003elike\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"last_name\"\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"j\"\u003c/span\u003e);\n        \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003egt\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"age\"\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e);\n        \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eisNotNull\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"email\"\u003c/span\u003e);\n        \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectList\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e);\n        \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n    }\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e运行结果：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-en\"\u003eEmployee\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003eid\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e1\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003elastName\u003c/span\u003e=\u003cspan class=\"pl-s1\"\u003ejack\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eemail\u003c/span\u003e=\u003cspan class=\"pl-smi\"\u003ejack\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-s1\"\u003eqq\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003ecom\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003eage\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e35\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtCreate\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003egmtModified\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e2021\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e04\u003c/span\u003e-\u003cspan class=\"pl-c1\"\u003e24\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eT21\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e14\u003c/span\u003e:\u003cspan class=\"pl-c1\"\u003e18\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003edeleted\u003c/span\u003e=\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e条件构造器提供了丰富的条件方法帮助我们进行条件的构造，比如 \u003ccode\u003elike\u003c/code\u003e 方法会为我们建立模糊查询，查看一下控制台输出的 SQL：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-sql notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"==\u0026gt;  Preparing: SELECT id,last_name,email,age,gmt_create,gmt_modified,is_deleted AS deleted FROM tbl_employee WHERE is_deleted=0 AND (last_name LIKE ? AND age \u0026gt; ? AND email IS NOT NULL)\n==\u0026gt; Parameters: %j%(String), 20(Integer)\"\u003e\u003cpre\u003e\u003cspan class=\"pl-k\"\u003e==\u0026gt;\u003c/span\u003e  Preparing: \u003cspan class=\"pl-k\"\u003eSELECT\u003c/span\u003e id,last_name,email,age,gmt_create,gmt_modified,is_deleted \u003cspan class=\"pl-k\"\u003eAS\u003c/span\u003e deleted \u003cspan class=\"pl-k\"\u003eFROM\u003c/span\u003e tbl_employee \u003cspan class=\"pl-k\"\u003eWHERE\u003c/span\u003e is_deleted\u003cspan class=\"pl-k\"\u003e=\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e \u003cspan class=\"pl-k\"\u003eAND\u003c/span\u003e (last_name \u003cspan class=\"pl-k\"\u003eLIKE\u003c/span\u003e ? \u003cspan class=\"pl-k\"\u003eAND\u003c/span\u003e age \u003cspan class=\"pl-k\"\u003e\u0026gt;\u003c/span\u003e ? \u003cspan class=\"pl-k\"\u003eAND\u003c/span\u003e email \u003cspan class=\"pl-k\"\u003eIS NOT NULL\u003c/span\u003e)\n\u003cspan class=\"pl-k\"\u003e==\u0026gt;\u003c/span\u003e Parameters: %j%(String), \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e(\u003cspan class=\"pl-k\"\u003eInteger\u003c/span\u003e)\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e可以看到它是对 \u003ccode\u003ej\u003c/code\u003e 的前后都加上了 \u003ccode\u003e%\u003c/code\u003e ，若是只想查询以 \u003ccode\u003ej\u003c/code\u003e 开头的名字，则可以使用 \u003ccode\u003elikeRight\u003c/code\u003e 方法，若是想查询以 \u003ccode\u003ej\u003c/code\u003e 结尾的名字，，则使用 \u003ccode\u003elikeLeft\u003c/code\u003e 方法。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e年龄的比较也是如此， \u003ccode\u003egt\u003c/code\u003e 是大于指定值，若是小于则调用 \u003ccode\u003elt\u003c/code\u003e ，大于等于调用 \u003ccode\u003ege\u003c/code\u003e ，小于等于调用 \u003ccode\u003ele\u003c/code\u003e ，不等于调用 \u003ccode\u003ene\u003c/code\u003e ，还可以使用 \u003ccode\u003ebetween\u003c/code\u003e 方法实现这一过程，相关的其它方法都可以查阅源码进行学习。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e因为这些方法返回的其实都是自身实例，所以可使用链式编程：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息\n    QueryWrapper\u0026lt;Employee\u0026gt; wrapper = new QueryWrapper\u0026lt;Employee\u0026gt;()\n        .likeLeft(\u0026quot;last_name\u0026quot;, \u0026quot;j\u0026quot;)\n        .gt(\u0026quot;age\u0026quot;, 20)\n        .isNotNull(\u0026quot;email\u0026quot;);\n    List\u0026lt;Employee\u0026gt; list = employeeMapper.selectList(wrapper);\n    list.forEach(System.out::println);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-c\"\u003e// 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003eQueryWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eQueryWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt;()\n        .\u003cspan class=\"pl-en\"\u003elikeLeft\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"last_name\"\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"j\"\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003egt\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"age\"\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003eisNotNull\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"email\"\u003c/span\u003e);\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectList\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e也可以使用 \u003ccode\u003eLambdaQueryWrapper\u003c/code\u003e 实现：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息\n    LambdaQueryWrapper\u0026lt;Employee\u0026gt; wrapper = new LambdaQueryWrapper\u0026lt;Employee\u0026gt;()\n        .like(Employee::getLastName,\u0026quot;j\u0026quot;)\n        .gt(Employee::getAge,20)\n        .isNotNull(Employee::getEmail);\n    List\u0026lt;Employee\u0026gt; list = employeeMapper.selectList(wrapper);\n    list.forEach(System.out::println);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-c\"\u003e// 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息\u003c/span\u003e\n    \u003cspan class=\"pl-smi\"\u003eLambdaQueryWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eLambdaQueryWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt;()\n        .\u003cspan class=\"pl-en\"\u003elike\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003egetLastName\u003c/span\u003e,\u003cspan class=\"pl-s\"\u003e\"j\"\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003egt\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003egetAge\u003c/span\u003e,\u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003eisNotNull\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003egetEmail\u003c/span\u003e);\n    \u003cspan class=\"pl-smi\"\u003eList\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e = \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eselectList\u003c/span\u003e(\u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003elist\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eforEach\u003c/span\u003e(\u003cspan class=\"pl-smi\"\u003eSystem\u003c/span\u003e.\u003cspan class=\"pl-s1\"\u003eout\u003c/span\u003e::\u003cspan class=\"pl-s1\"\u003eprintln\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e这种方式的好处在于对字段的设置不是硬编码，而是采用方法引用的形式，效果与 \u003ccode\u003eQueryWrapper\u003c/code\u003e 是一样的。\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eUpdateWrapper\u003c/code\u003e 与 \u003ccode\u003eQueryWrapper\u003c/code\u003e 不同，它的作用是封装更新内容的，比如：\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"@Test\nvoid contextLoads() {\n    UpdateWrapper\u0026lt;Employee\u0026gt; wrapper = new UpdateWrapper\u0026lt;Employee\u0026gt;()\n        .set(\u0026quot;age\u0026quot;, 50)\n        .set(\u0026quot;email\u0026quot;, \u0026quot;emp@163.com\u0026quot;)\n        .like(\u0026quot;last_name\u0026quot;, \u0026quot;j\u0026quot;)\n        .gt(\u0026quot;age\u0026quot;, 20);\n    employeeMapper.update(null, wrapper);\n}\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003e@\u003c/span\u003e\u003cspan class=\"pl-c1\"\u003eTest\u003c/span\u003e\n\u003cspan class=\"pl-smi\"\u003evoid\u003c/span\u003e \u003cspan class=\"pl-en\"\u003econtextLoads\u003c/span\u003e() {\n    \u003cspan class=\"pl-smi\"\u003eUpdateWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt; \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e = \u003cspan class=\"pl-k\"\u003enew\u003c/span\u003e \u003cspan class=\"pl-smi\"\u003eUpdateWrapper\u003c/span\u003e\u0026lt;\u003cspan class=\"pl-smi\"\u003eEmployee\u003c/span\u003e\u0026gt;()\n        .\u003cspan class=\"pl-en\"\u003eset\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"age\"\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e50\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003eset\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"email\"\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"emp@163.com\"\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003elike\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"last_name\"\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\"j\"\u003c/span\u003e)\n        .\u003cspan class=\"pl-en\"\u003egt\u003c/span\u003e(\u003cspan class=\"pl-s\"\u003e\"age\"\u003c/span\u003e, \u003cspan class=\"pl-c1\"\u003e20\u003c/span\u003e);\n    \u003cspan class=\"pl-s1\"\u003eemployeeMapper\u003c/span\u003e.\u003cspan class=\"pl-en\"\u003eupdate\u003c/span\u003e(\u003cspan class=\"pl-c1\"\u003enull\u003c/span\u003e, \u003cspan class=\"pl-s1\"\u003ewrapper\u003c/span\u003e);\n}\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e将名字中包含 \u003ccode\u003ej\u003c/code\u003e 且年龄大于 20 岁的员工年龄改为 50，邮箱改为 \u003ca href=\"mailto:emp@163.com\"\u003eemp@163.com\u003c/a\u003e，\u003ccode\u003eUpdateWrapper\u003c/code\u003e 不仅能够封装更新内容，也能作为查询条件，所以在更新数据时可以直接构造一个 \u003ccode\u003eUpdateWrapper\u003c/code\u003e 来设置更新内容和条件。\u003c/p\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"CRUD","fully_qualified_name":"CRUD","kind":"section_2","ident_start":467,"ident_end":471,"extent_start":464,"extent_end":7862,"ident_utf16":{"start":{"line_number":6,"utf16_col":3},"end":{"line_number":6,"utf16_col":7}},"extent_utf16":{"start":{"line_number":6,"utf16_col":0},"end":{"line_number":262,"utf16_col":0}}},{"name":"ID 策略","fully_qualified_name":"ID 策略","kind":"section_2","ident_start":7865,"ident_end":7874,"extent_start":7862,"extent_end":12511,"ident_utf16":{"start":{"line_number":262,"utf16_col":3},"end":{"line_number":262,"utf16_col":8}},"extent_utf16":{"start":{"line_number":262,"utf16_col":0},"end":{"line_number":354,"utf16_col":0}}},{"name":"属性自动填充","fully_qualified_name":"属性自动填充","kind":"section_2","ident_start":12514,"ident_end":12532,"extent_start":12511,"extent_end":18198,"ident_utf16":{"start":{"line_number":354,"utf16_col":3},"end":{"line_number":354,"utf16_col":9}},"extent_utf16":{"start":{"line_number":354,"utf16_col":0},"end":{"line_number":528,"utf16_col":0}}},{"name":"逻辑删除","fully_qualified_name":"逻辑删除","kind":"section_2","ident_start":18201,"ident_end":18213,"extent_start":18198,"extent_end":23884,"ident_utf16":{"start":{"line_number":528,"utf16_col":3},"end":{"line_number":528,"utf16_col":7}},"extent_utf16":{"start":{"line_number":528,"utf16_col":0},"end":{"line_number":652,"utf16_col":0}}},{"name":"分页插件","fully_qualified_name":"分页插件","kind":"section_2","ident_start":23887,"ident_end":23899,"extent_start":23884,"extent_end":26233,"ident_utf16":{"start":{"line_number":652,"utf16_col":3},"end":{"line_number":652,"utf16_col":7}},"extent_utf16":{"start":{"line_number":652,"utf16_col":0},"end":{"line_number":720,"utf16_col":0}}},{"name":"乐观锁","fully_qualified_name":"乐观锁","kind":"section_2","ident_start":26236,"ident_end":26245,"extent_start":26233,"extent_end":31544,"ident_utf16":{"start":{"line_number":720,"utf16_col":3},"end":{"line_number":720,"utf16_col":6}},"extent_utf16":{"start":{"line_number":720,"utf16_col":0},"end":{"line_number":873,"utf16_col":0}}},{"name":"条件构造器","fully_qualified_name":"条件构造器","kind":"section_2","ident_start":31547,"ident_end":31562,"extent_start":31544,"extent_end":35887,"ident_utf16":{"start":{"line_number":873,"utf16_col":3},"end":{"line_number":873,"utf16_col":8}},"extent_utf16":{"start":{"line_number":873,"utf16_col":0},"end":{"line_number":975,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":159422409,"defaultBranch":"master","name":"springboot-guide","ownerLogin":"CodingDocs","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2018-11-28T01:05:07.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/80885507?v=4","public":true,"private":false,"isOrgOwned":true,"isArchived":false},"currentUser":null,"uploadToken":"M4lNKGeUJF5_WLQxBeRN8e9TluIdpjLyawAAgaYrwxuJ-Ftuiq1dTN0PIyHTpje6Il__KA74185eEoyfjSWvJw","allShortcutsEnabled":false,"treeExpanded":true,"path":"docs/MyBatisPlus.md","symbolsExpanded":false,"refInfo":{"name":"master","listCacheKey":"v0:1543367116.0","canEdit":false,"currentOid":"c9d3479f879a7ae26a3af03a7f3bb652f55a976c"},"helpUrl":"https://docs.github.com","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"docs":{"items":[{"name":"advanced","path":"docs/advanced","contentType":"directory"},{"name":"basis","path":"docs/basis","contentType":"directory"},{"name":"projects","path":"docs/projects","contentType":"directory"},{"name":"start","path":"docs/start","contentType":"directory"},{"name":"MyBatisPlus.md","path":"docs/MyBatisPlus.md","contentType":"file"},{"name":"PowerMockRunnerAndMockito.md","path":"docs/PowerMockRunnerAndMockito.md","contentType":"file"},{"name":"spring-bean-validation.md","path":"docs/spring-bean-validation.md","contentType":"file"}],"totalCount":7},"":{"items":[{"name":"docs","path":"docs","contentType":"directory"},{"name":"media","path":"media","contentType":"directory"},{"name":"source-code","path":"source-code","contentType":"directory"},{"name":".gitattributes","path":".gitattributes","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".nojekyll","path":".nojekyll","contentType":"file"},{"name":"404.md","path":"404.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"_coverpage.md","path":"_coverpage.md","contentType":"file"},{"name":"index.html","path":"index.html","contentType":"file"}],"totalCount":11}},"fileTreeProcessingTime":8.102580999999999,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"master","listCacheKey":"v0:1543367116.0","canEdit":false,"refType":"branch","currentOid":"c9d3479f879a7ae26a3af03a7f3bb652f55a976c","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"docs/MyBatisPlus.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/CodingDocs/springboot-guide/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"MyBatisPlus.md","displayUrl":"https://github.com/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md?raw=true","headerInfo":{"blobSize":"35 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"afd4043","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2FCodingDocs%2Fspringboot-guide%2Fblob%2Fmaster%2Fdocs%2FMyBatisPlus.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"975","truncatedSloc":"763"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"isIssueTemplate":false,"isDiscussionTemplate":false,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/CodingDocs/springboot-guide/blob/master/docs/MyBatisPlus.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/CodingDocs/springboot-guide/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/CodingDocs/springboot-guide/raw/refs/heads/master/docs/MyBatisPlus.md","renderImageOrRaw":false,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null},"copilotInfo":null,"copilotAccessAllowed":false,"copilotSpacesEnabled":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"isMarketplaceEnabled":true},"codeViewBlobLayoutRoute.StyledBlob":{"rawLines":["`MyBatis` 是一款优秀的持久层框架，它支持定制化 SQL、存储过程以及高级映射，而实际开发中，我们都会选择使用 `MyBatisPlus`，它是对 `MyBatis` 框架的进一步增强，能够极大地简化我们的持久层代码，下面就一起来看看 `MyBatisPlus` 中的一些奇淫巧技吧。","","\u003e 说明：本篇文章需要一定的 `MyBatis` 与 `MyBatisPlus` 基础","","MyBatis-Plus 官网地址 ： https://baomidou.com/ 。","","## CRUD","","使用 `MyBatisPlus` 实现业务的增删改查非常地简单，一起来看看吧。","","**1.首先新建一个 SpringBoot 工程，然后引入依赖：**","","```xml","\u003cdependency\u003e","  \u003cgroupId\u003ecom.baomidou\u003c/groupId\u003e","  \u003cartifactId\u003emybatis-plus-boot-starter\u003c/artifactId\u003e","  \u003cversion\u003e3.4.2\u003c/version\u003e","\u003c/dependency\u003e","\u003cdependency\u003e","  \u003cgroupId\u003emysql\u003c/groupId\u003e","  \u003cartifactId\u003emysql-connector-java\u003c/artifactId\u003e","  \u003cscope\u003eruntime\u003c/scope\u003e","\u003c/dependency\u003e","\u003cdependency\u003e","  \u003cgroupId\u003eorg.projectlombok\u003c/groupId\u003e","  \u003cartifactId\u003elombok\u003c/artifactId\u003e","\u003c/dependency\u003e","```","","**2.配置一下数据源：**","","```yaml","spring:","  datasource:","    driver-class-name: com.mysql.cj.jdbc.Driver","    username: root","    url: jdbc:mysql:///mybatisplus?serverTimezone=UTC","    password: 123456","```","","**3.创建一下数据表：**","","```sql","CREATE DATABASE `mybatisplus`;","","USE `mybatisplus`;","","DROP TABLE IF EXISTS `tbl_employee`;","","CREATE TABLE `tbl_employee` (","  `id` bigint(20) NOT NULL,","  `last_name` varchar(255) DEFAULT NULL,","  `email` varchar(255) DEFAULT NULL,","  `gender` char(1) DEFAULT NULL,","  `age` int(11) DEFAULT NULL,","  PRIMARY KEY (`id`)",") ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=gbk;","","insert  into `tbl_employee`(`id`,`last_name`,`email`,`gender`,`age`) values (1,'jack','jack@qq.com','1',35),(2,'tom','tom@qq.com','1',30),(3,'jerry','jerry@qq.com','1',40);","```","","**4.创建对应的实体类：**","","```java","@Data","public class Employee {","","    private Long id;","    private String lastName;","    private String email;","    private Integer age;","}","```","","**4.编写 `Mapper` 接口：**","","```java","public interface EmployeeMapper extends BaseMapper\u003cEmployee\u003e {","}","```","","我们只需继承 `MyBatisPlus` 提供的 `BaseMapper` 接口即可，现在我们就拥有了对 `Employee` 进行增删改查的 API，比如：","","```java","@SpringBootTest","@MapperScan(\"com.wwj.mybatisplusdemo.mapper\")","class MybatisplusDemoApplicationTests {","","    @Autowired","    private EmployeeMapper employeeMapper;","","    @Test","    void contextLoads() {","        List\u003cEmployee\u003e employees = employeeMapper.selectList(null);","        employees.forEach(System.out::println);","    }","}","```","","运行结果：","","```java","org.springframework.jdbc.BadSqlGrammarException:","### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'mybatisplus.employee' doesn't exist","```","","程序报错了，原因是不存在 `employee` 表，这是因为我们的实体类名为 `Employee`，`MyBatisPlus` 默认是以类名作为表名进行操作的，可如果类名和表名不相同（实际开发中也确实可能不同），就需要在实体类中使用 `@TableName` 注解来声明表的名称：","","```java","@Data","@TableName(\"tbl_employee\") // 声明表名称","public class Employee {","","    private Long id;","    private String lastName;","    private String email;","    private Integer age;","}","```","","重新执行测试代码，结果如下：","","```java","Employee(id=1, lastName=jack, email=jack@qq.com, age=35)","Employee(id=2, lastName=tom, email=tom@qq.com, age=30)","Employee(id=3, lastName=jerry, email=jerry@qq.com, age=40)","```","","`BaseMapper` 提供了常用的一些增删改查方法：","","![](https://img-blog.csdnimg.cn/20210519084059865.png)","","具体细节可以查阅其源码自行体会，注释都是中文的，非常容易理解。","","在开发过程中，我们通常会使用 `Service` 层来调用 `Mapper` 层的方法，而 `MyBatisPlus` 也为我们提供了通用的 `Service`：","","```java","public interface EmployeeService extends IService\u003cEmployee\u003e {","}","","@Service","public class EmployeeServiceImpl extends ServiceImpl\u003cEmployeeMapper, Employee\u003e implements EmployeeService {","}","```","","事实上，我们只需让 `EmployeeServiceImpl` 继承 `ServiceImpl` 即可获得 `Service` 层的方法，**那么为什么还需要实现 `EmployeeService` 接口呢？**","","这是因为实现 `EmployeeService` 接口能够更方便地对业务进行扩展，一些复杂场景下的数据处理，`MyBatisPlus` 提供的 `Service` 方法可能无法处理，此时我们就需要自己编写代码，这时候只需在 `EmployeeService` 中定义自己的方法，并在 `EmployeeServiceImpl` 中实现即可。","","先来测试一下 `MyBatisPlus` 提供的 `Service` 方法：","","```java","@SpringBootTest","@MapperScan(\"com.wwj.mybatisplusdemo.mapper\")","class MybatisplusDemoApplicationTests {","","    @Autowired","    private EmployeeService employeeService;","","    @Test","    void contextLoads() {","        List\u003cEmployee\u003e list = employeeService.list();","        list.forEach(System.out::println);","    }","}","```","","运行结果：","","```java","Employee(id=1, lastName=jack, email=jack@qq.com, age=35)","Employee(id=2, lastName=tom, email=tom@qq.com, age=30)","Employee(id=3, lastName=jerry, email=jerry@qq.com, age=40)","```","","接下来模拟一个自定义的场景，我们来编写自定义的操作方法，首先在 `EmployeeMapper` 中进行声明：","","```java","public interface EmployeeMapper extends BaseMapper\u003cEmployee\u003e {","","    List\u003cEmployee\u003e selectAllByLastName(@Param(\"lastName\") String lastName);","}","```","","此时我们需要自己编写配置文件实现该方法，在 `resource` 目录下新建一个 `mapper` 文件夹，然后在该文件夹下创建 `EmployeeMapper.xml` 文件：","","```xml","\u003c!DOCTYPE mapper","        PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"","        \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"\u003e","","\u003cmapper namespace=\"com.wwj.mybatisplusdemo.mapper.EmployeeMapper\"\u003e","","    \u003csql id=\"Base_Column\"\u003e","        id, last_name, email, gender, age","    \u003c/sql\u003e","","    \u003cselect id=\"selectAllByLastName\" resultType=\"com.wwj.mybatisplusdemo.bean.Employee\"\u003e","        select \u003cinclude refid=\"Base_Column\"/\u003e","        from tbl_employee","        where last_name = #{lastName}","    \u003c/select\u003e","\u003c/mapper\u003e","```","","`MyBatisPlus` 默认扫描的是类路径下的 `mapper` 目录，这可以从源码中得到体现：","","![](https://img-blog.csdnimg.cn/20210519084046472.png)","","所以我们直接将 `Mapper` 配置文件放在该目录下就没有任何问题，可如果不是这个目录，我们就需要进行配置，比如：","","```yaml","mybatis-plus:","  mapper-locations: classpath:xml/*.xml","```","","编写好 `Mapper` 接口后，我们就需要定义 `Service` 方法了：","","```java","public interface EmployeeService extends IService\u003cEmployee\u003e {","","    List\u003cEmployee\u003e listAllByLastName(String lastName);","}","","@Service","public class EmployeeServiceImpl extends ServiceImpl\u003cEmployeeMapper, Employee\u003e implements EmployeeService {","","    @Override","    public List\u003cEmployee\u003e listAllByLastName(String lastName) {","        return baseMapper.selectAllByLastName(lastName);","    }","}","```","","在 `EmployeeServiceImpl` 中我们无需将 `EmployeeMapper` 注入进来，而是使用 `BaseMapper`，查看 `ServiceImpl` 的源码：","","![](https://img-blog.csdnimg.cn/2021051908403249.png)","","可以看到它为我们注入了一个 `BaseMapper` 对象，而它是第一个泛型类型，也就是 `EmployeeMapper` 类型，所以我们可以直接使用这个 `baseMapper` 来调用 `Mapper` 中的方法，此时编写测试代码：","","```java","@SpringBootTest","@MapperScan(\"com.wwj.mybatisplusdemo.mapper\")","class MybatisplusDemoApplicationTests {","","    @Autowired","    private EmployeeService employeeService;","","    @Test","    void contextLoads() {","        List\u003cEmployee\u003e list = employeeService.listAllByLastName(\"tom\");","        list.forEach(System.out::println);","    }","}","```","","运行结果：","","```java","Employee(id=2, lastName=tom, email=tom@qq.com, age=30)","```","","## ID 策略","","在创建表的时候我故意没有设置主键的增长策略，现在我们来插入一条数据，看看主键是如何增长的：","","```java","@Test","void contextLoads() {","    Employee employee = new Employee();","    employee.setLastName(\"lisa\");","    employee.setEmail(\"lisa@qq.com\");","    employee.setAge(20);","    employeeService.save(employee);","}","```","","插入成功后查询一下数据表：","","```sql","mysql\u003e select * from tbl_employee;","+---------------------+-----------+--------------+--------+------+","| id                  | last_name | email        | gender | age  |","+---------------------+-----------+--------------+--------+------+","|                   1 | jack      | jack@qq.com  | 1      |   35 |","|                   2 | tom       | tom@qq.com   | 1      |   30 |","|                   3 | jerry     | jerry@qq.com | 1      |   40 |","| 1385934720849584129 | lisa      | lisa@qq.com  | NULL   |   20 |","+---------------------+-----------+--------------+--------+------+","4 rows in set (0.00 sec)","```","","可以看到 id 是一串相当长的数字，这是什么意思呢？提前剧透一下，这其实是分布式 id，那又何为分布式 id 呢？","","我们知道，对于一个大型应用，其访问量是非常巨大的，就比如说一个网站每天都有人进行注册，注册的用户信息就需要存入数据表，随着日子一天天过去，数据表中的用户越来越多，此时数据库的查询速度就会受到影响，所以一般情况下，当数据量足够庞大时，数据都会做分库分表的处理。","","然而，一旦分表，问题就产生了，很显然这些分表的数据都是属于同一张表的数据，只是因为数据量过大而分成若干张表，那么这几张表的主键 id 该怎么管理呢？每张表维护自己的 id？那数据将会有很多的 id 重复，这当然是不被允许的，其实，我们可以使用算法来生成一个绝对不会重复的 id，这样问题就迎刃而解了，事实上，分布式 id 的解决方案有很多：","","1. UUID","1. SnowFlake","1. TinyID","1. Uidgenerator","1. Leaf","6. Tinyid","7. ......","","以 UUID 为例，它生成的是一串由数字和字母组成的字符串，显然并不适合作为数据表的 id，而且 id 保持递增有序会加快表的查询效率，基于此，`MyBatisPlus` 使用的就是 `SnowFlake`（雪花算法）。","","`Snowflake` 是 Twitter 开源的分布式 ID 生成算法。`Snowflake` 由 64 bit 的二进制数字组成，这 64bit 的二进制被分成了几部分，每一部分存储的数据都有特定的含义：","","- **第 0 位**： 符号位（标识正负），始终为 0，没有用，不用管。","- **第 1~41 位** ：一共 41 位，用来表示时间戳，单位是毫秒，可以支撑 2 ^41 毫秒（约 69 年）","- **第 42~52 位** ：一共 10 位，一般来说，前 5 位表示机房 ID，后 5 位表示机器 ID（实际项目中可以根据实际情况调整）。这样就可以区分不同集群/机房的节点。","- **第 53~64 位** ：一共 12 位，用来表示序列号。 序列号为自增值，代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。","","![](https://oscimg.oschina.net/oscnet/up-a7e54a77b5ab1d9fa16d5ae3a3c50c5aee9.png)","","这也就是为什么插入数据后新的数据 id 是一长串数字的原因了，我们可以在实体类中使用 `@TableId` 来设置主键的策略：","","```java","@Data","@TableName(\"tbl_employee\")","public class Employee {","","    @TableId(type = IdType.AUTO) // 设置主键策略","    private Long id;","    private String lastName;","    private String email;","    private Integer age;","}","```","","`MyBatisPlus` 提供了几种主键的策略：","![](https://img-blog.csdnimg.cn/20210519084011745.png)","其中 `AUTO` 表示数据库自增策略，该策略下需要数据库实现主键的自增（auto_increment)，`ASSIGN_ID` 是雪花算法，默认使用的是该策略，`ASSIGN_UUID` 是 UUID 策略，一般不会使用该策略。","","这里多说一点， 当实体类的主键名为 id，并且数据表的主键名也为 id 时，此时 `MyBatisPlus` 会自动判定该属性为主键 id，倘若名字不是 id 时，就需要标注 `@TableId` 注解，若是实体类中主键名与数据表的主键名不一致，则可以进行声明：","","```java","@TableId(value = \"uid\",type = IdType.AUTO) // 设置主键策略","private Long id;","```","","还可以在配置文件中配置全局的主键策略：","","```yaml","mybatis-plus:","  global-config:","    db-config:","      id-type: auto","```","","这样能够避免在每个实体类中重复设置主键策略。","","## 属性自动填充","","翻阅《阿里巴巴Java开发手册》，在第 5 章 MySQL 数据库可以看到这样一条规范：","![](https://img-blog.csdnimg.cn/20210426214821389.png)","对于一张数据表，它必须具备三个字段：","","- `id` : 唯一ID","- `gmt_create` : 保存的是当前数据创建的时间","- `gmt_modified` : 保存的是更新时间","","我们改造一下数据表：","","```sql","alter table tbl_employee add column gmt_create datetime not null;","alter table tbl_employee add column gmt_modified datetime not null;","```","","然后改造一下实体类：","","```java","@Data","@TableName(\"tbl_employee\")","public class Employee {","","    @TableId(type = IdType.AUTO) // 设置主键策略","    private Long id;","    private String lastName;","    private String email;","    private Integer age;","    private LocalDateTime gmtCreate;","    private LocalDateTime gmtModified;","}","```","","此时我们在插入数据和更新数据的时候就需要手动去维护这两个属性：","","```java","@Test","void contextLoads() {","    Employee employee = new Employee();","    employee.setLastName(\"lisa\");","    employee.setEmail(\"lisa@qq.com\");","    employee.setAge(20);","    // 设置创建时间","    employee.setGmtCreate(LocalDateTime.now());","    employee.setGmtModified(LocalDateTime.now());","    employeeService.save(employee);","}","","@Test","void contextLoads() {","    Employee employee = new Employee();","    employee.setId(1385934720849584130L);","    employee.setAge(50);","    // 设置创建时间","    employee.setGmtModified(LocalDateTime.now());","    employeeService.updateById(employee);","}","```","","每次都需要维护这两个属性未免过于麻烦，好在 `MyBatisPlus` 提供了字段自动填充功能来帮助我们进行管理，需要使用到的是 `@TableField` 注解：","","```java","@Data","@TableName(\"tbl_employee\")","public class Employee {","","    @TableId(type = IdType.AUTO)","    private Long id;","    private String lastName;","    private String email;","    private Integer age;","    @TableField(fill = FieldFill.INSERT) // 插入的时候自动填充","    private LocalDateTime gmtCreate;","    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新的时候自动填充","    private LocalDateTime gmtModified;","}","```","","然后编写一个类实现 MetaObjectHandler 接口：","","```java","@Component","@Slf4j","public class MyMetaObjectHandler implements MetaObjectHandler {","","    /**","     * 实现插入时的自动填充","     * @param metaObject","     */","    @Override","    public void insertFill(MetaObject metaObject) {","        log.info(\"insert开始属性填充\");","        this.strictInsertFill(metaObject,\"gmtCreate\", LocalDateTime.class,LocalDateTime.now());","        this.strictInsertFill(metaObject,\"gmtModified\", LocalDateTime.class,LocalDateTime.now());","    }","","    /**","     * 实现更新时的自动填充","     * @param metaObject","     */","    @Override","    public void updateFill(MetaObject metaObject) {","        log.info(\"update开始属性填充\");","        this.strictInsertFill(metaObject,\"gmtModified\", LocalDateTime.class,LocalDateTime.now());","    }","}","```","","该接口中有两个未实现的方法，分别为插入和更新时的填充方法，在方法中调用 `strictInsertFill()` 方法 即可实现属性的填充，它需要四个参数：","","1. `metaObject`：元对象，就是方法的入参","1. `fieldName`：为哪个属性进行自动填充","1. `fieldType`：属性的类型","1. `fieldVal`：需要填充的属性值","","此时在插入和更新数据之前，这两个方法会先被执行，以实现属性的自动填充，通过日志我们可以进行验证：","","```java","@Test","void contextLoads() {","    Employee employee = new Employee();","    employee.setId(1385934720849584130L);","    employee.setAge(15);","    employeeService.updateById(employee);","}","```","","运行结果：","","```java","INFO 15584 --- [           main] c.w.m.handler.MyMetaObjectHandler        : update开始属性填充","2021-04-24 21:32:19.788  INFO 15584 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...","2021-04-24 21:32:21.244  INFO 15584 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.","```","","属性填充其实可以进行一些优化，考虑一些特殊情况，对于一些不存在的属性，就不需要进行属性填充，对于一些设置了值的属性，也不需要进行属性填充，这样可以提高程序的整体运行效率：","","```java","@Component","@Slf4j","public class MyMetaObjectHandler implements MetaObjectHandler {","","    @Override","    public void insertFill(MetaObject metaObject) {","        boolean hasGmtCreate = metaObject.hasSetter(\"gmtCreate\");","        boolean hasGmtModified = metaObject.hasSetter(\"gmtModified\");","        if (hasGmtCreate) {","            Object gmtCreate = this.getFieldValByName(\"gmtCreate\", metaObject);","            if (gmtCreate == null) {","                this.strictInsertFill(metaObject, \"gmtCreate\", LocalDateTime.class, LocalDateTime.now());","            }","        }","        if (hasGmtModified) {","            Object gmtModified = this.getFieldValByName(\"gmtModified\", metaObject);","            if (gmtModified == null) {","                this.strictInsertFill(metaObject, \"gmtModified\", LocalDateTime.class, LocalDateTime.now());","            }","        }","    }","","    @Override","    public void updateFill(MetaObject metaObject) {","        boolean hasGmtModified = metaObject.hasSetter(\"gmtModified\");","        if (hasGmtModified) {","            Object gmtModified = this.getFieldValByName(\"gmtModified\", metaObject);","            if (gmtModified == null) {","                this.strictInsertFill(metaObject, \"gmtModified\", LocalDateTime.class, LocalDateTime.now());","            }","        }","    }","}","```","","## 逻辑删除","","逻辑删除对应的是物理删除，分别介绍一下这两个概念：","","1. **物理删除** ：指的是真正的删除，即：当执行删除操作时，将数据表中的数据进行删除，之后将无法再查询到该数据","1. **逻辑删除** ：并不是真正意义上的删除，只是对于用户不可见了，它仍然存在与数据表中","","在这个数据为王的时代，数据就是财富，所以一般并不会有哪个系统在删除某些重要数据时真正删掉了数据，通常都是在数据库中建立一个状态列，让其默认为 0，当为 0 时，用户可见；当执行了删除操作，就将状态列改为 1，此时用户不可见，但数据还是在表中的。","","![](https://img-blog.csdnimg.cn/20210426215107210.png)","","按照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议，我们来为数据表新增一个`is_deleted` 字段：","","```sql","alter table tbl_employee add column is_deleted tinyint not null;","```","","在实体类中也要添加这一属性：","","```java","@Data","@TableName(\"tbl_employee\")","public class Employee {","","    @TableId(type = IdType.AUTO)","    private Long id;","    private String lastName;","    private String email;","    private Integer age;","    @TableField(fill = FieldFill.INSERT)","    private LocalDateTime gmtCreate;","    @TableField(fill = FieldFill.INSERT_UPDATE)","    private LocalDateTime gmtModified;","    /**","     * 逻辑删除属性","     */","    @TableLogic","    @TableField(\"is_deleted\")","    private Boolean deleted;","}","```","","![](https://img-blog.csdnimg.cn/2021042621530162.png)","","还是参照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议，对于布尔类型变量，不能加 is 前缀，所以我们的属性被命名为 `deleted`，但此时就无法与数据表的字段进行对应了，所以我们需要使用 `@TableField` 注解来声明一下数据表的字段名，而 `@TableLogin` 注解用于设置逻辑删除属性；此时我们执行删除操作：","","```java","@Test","void contextLoads() {","    employeeService.removeById(3);","}","```","","查询数据表：","","```sql","mysql\u003e select * from tbl_employee;","+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+","| id                  | last_name | email        | gender | age  | gmt_create          | gmt_modified        | is_deleted |","+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+","|                   1 | jack      | jack@qq.com  | 1      |   35 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |","|                   2 | tom       | tom@qq.com   | 1      |   30 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |","|                   3 | jerry     | jerry@qq.com | 1      |   40 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          1 |","| 1385934720849584129 | lisa      | lisa@qq.com  | NULL   |   20 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |","| 1385934720849584130 | lisa      | lisa@qq.com  | NULL   |   15 | 2021-04-24 21:14:18 | 2021-04-24 21:32:19 |          0 |","+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+","5 rows in set (0.00 sec)","```","","可以看到数据并没有被删除，只是 `is_deleted` 字段的属性值被更新成了 1，此时我们再来执行查询操作：","","```java","@Test","void contextLoads() {","    List\u003cEmployee\u003e list = employeeService.list();","    list.forEach(System.out::println);","}","```","","执行结果：","","```java","Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)","Employee(id=2, lastName=tom, email=tom@qq.com, age=30, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)","Employee(id=1385934720849584129, lastName=lisa, email=lisa@qq.com, age=20, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)","Employee(id=1385934720849584130, lastName=lisa, email=lisa@qq.com, age=15, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:32:19, deleted=false)","```","","会发现第三条数据并没有被查询出来，它是如何实现的呢？我们可以输出 `MyBatisPlus` 生成的 SQL 来分析一下，在配置文件中进行配置：","","```yaml","mybatis-plus:","  configuration:","    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出SQL日志","```","","运行结果：","","```java","==\u003e  Preparing: SELECT id,last_name,email,age,gmt_create,gmt_modified,is_deleted AS deleted FROM tbl_employee WHERE is_deleted=0","==\u003e Parameters:","\u003c==    Columns: id, last_name, email, age, gmt_create, gmt_modified, deleted","\u003c==        Row: 1, jack, jack@qq.com, 35, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0","\u003c==        Row: 2, tom, tom@qq.com, 30, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0","\u003c==        Row: 1385934720849584129, lisa, lisa@qq.com, 20, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0","\u003c==        Row: 1385934720849584130, lisa, lisa@qq.com, 15, 2021-04-24 21:14:18, 2021-04-24 21:32:19, 0","\u003c==      Total: 4","```","","原来它在查询时携带了一个条件： `is_deleted=0` ，这也说明了 `MyBatisPlus` 默认 0 为不删除，1 为删除。","若是你想修改这个规定，比如设置-1 为删除，1 为不删除，也可以进行配置：","","```yaml","mybatis-plus:","  global-config:","    db-config:","      id-type: auto","      logic-delete-field: deleted # 逻辑删除属性名","      logic-delete-value: -1 # 删除值","      logic-not-delete-value: 1 # 不删除值","```","","但建议使用默认的配置，阿里巴巴开发手册也规定 1 表示删除，0 表示未删除。","","## 分页插件","","对于分页功能，`MyBatisPlus` 提供了分页插件，只需要进行简单的配置即可实现：","","```java","@Configuration","public class MyBatisConfig {","","    /**","     * 注册分页插件","     * @return","     */","    @Bean","    public MybatisPlusInterceptor mybatisPlusInterceptor() {","        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();","        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));","        return interceptor;","    }","}","```","","接下来我们就可以使用分页插件提供的功能了：","","```java","@Test","void contextLoads() {","    Page\u003cEmployee\u003e page = new Page\u003c\u003e(1,2);","    employeeService.page(page, null);","    List\u003cEmployee\u003e employeeList = page.getRecords();","    employeeList.forEach(System.out::println);","    System.out.println(\"获取总条数:\" + page.getTotal());","    System.out.println(\"获取当前页码:\" + page.getCurrent());","    System.out.println(\"获取总页码:\" + page.getPages());","    System.out.println(\"获取每页显示的数据条数:\" + page.getSize());","    System.out.println(\"是否有上一页:\" + page.hasPrevious());","    System.out.println(\"是否有下一页:\" + page.hasNext());","}","```","","其中的 `Page` 对象用于指定分页查询的规则，这里表示按每页两条数据进行分页，并查询第一页的内容，运行结果：","","```java","Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)","Employee(id=2, lastName=tom, email=tom@qq.com, age=30, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)","获取总条数:4","获取当前页码:1","获取总页码:2","获取每页显示的数据条数:2","是否有上一页:false","是否有下一页:true","```","","倘若在分页过程中需要限定一些条件，我们就需要构建 QueryWrapper 来实现：","","```java","@Test","void contextLoads() {","    Page\u003cEmployee\u003e page = new Page\u003c\u003e(1, 2);","    employeeService.page(page, new QueryWrapper\u003cEmployee\u003e()","                         .between(\"age\", 20, 50)","                         .eq(\"gender\", 1));","    List\u003cEmployee\u003e employeeList = page.getRecords();","    employeeList.forEach(System.out::println);","}","```","","此时分页的数据就应该是年龄在 20~50 岁之间，且 gender 值为 1 的员工信息，然后再对这些数据进行分页。","","## 乐观锁","","当程序中出现并发访问时，就需要保证数据的一致性。以商品系统为例，现在有两个管理员均想对同一件售价为 100 元的商品进行修改，A 管理员正准备将商品售价改为 150 元，但此时出现了网络问题，导致 A 管理员的操作陷入了等待状态；此时 B 管理员也进行修改，将商品售价改为了 200 元，修改完成后 B 管理员退出了系统，此时 A 管理员的操作也生效了，这样便使得 A 管理员的操作直接覆盖了 B 管理员的操作，B 管理员后续再进行查询时会发现商品售价变为了 150 元，这样的情况是绝对不允许发生的。","","要想解决这一问题，可以给数据表加锁，常见的方式有两种：","","1. 乐观锁","1. 悲观锁","","悲观锁认为并发情况一定会发生，所以在某条数据被修改时，为了避免其它人修改，会直接对数据表进行加锁，它依靠的是数据库本身提供的锁机制（表锁、行锁、读锁、写锁）。","","而乐观锁则相反，它认为数据产生冲突的情况一般不会发生，所以在修改数据的时候并不会对数据表进行加锁的操作，而是在提交数据时进行校验，判断提交上来的数据是否会发生冲突，如果发生冲突，则提示用户重新进行操作，一般的实现方式为 `设置版本号字段` 。","","就以商品售价为例，在该表中设置一个版本号字段，让其初始为 1，此时 A 管理员和 B 管理员同时需要修改售价，它们会先读取到数据表中的内容，此时两个管理员读取到的版本号都为 1，此时 B 管理员的操作先生效了，它就会将当前数据表中对应数据的版本号与最开始读取到的版本号作一个比对，发现没有变化，于是修改就生效了，此时版本号加 1。","","而 A 管理员马上也提交了修改操作，但是此时的版本号为 2，与最开始读取到的版本号并不对应，这就说明数据发生了冲突，此时应该提示 A 管理员操作失败，并让 A 管理员重新查询一次数据。","","![](https://img-blog.csdnimg.cn/20210426221408623.png)","","乐观锁的优势在于采取了更加宽松的加锁机制，能够提高程序的吞吐量，适用于读操作多的场景。","","那么接下来我们就来模拟这一过程。","","**1.创建一张新的数据表：**","","```sql","create table shop(","\tid bigint(20) not null auto_increment,","  name varchar(30) not null,","  price int(11) default 0,","  version int(11) default 1,","  primary key(id)",");","","insert into shop(id,name,price) values(1,'笔记本电脑',8000);","```","","**2.创建实体类：**","","```java","@Data","public class Shop {","","    private Long id;","    private String name;","    private Integer price;","    private Integer version;","}","```","","**3.创建对应的 `Mapper` 接口：**","","```java","public interface ShopMapper extends BaseMapper\u003cShop\u003e {","}","```","","**4.编写测试代码：**","","```java","@SpringBootTest","@MapperScan(\"com.wwj.mybatisplusdemo.mapper\")","class MybatisplusDemoApplicationTests {","","    @Autowired","    private ShopMapper shopMapper;","","    /**","     * 模拟并发场景","     */","    @Test","    void contextLoads() {","        // A、B管理员读取数据","        Shop A = shopMapper.selectById(1L);","        Shop B = shopMapper.selectById(1L);","        // B管理员先修改","        B.setPrice(9000);","        int result = shopMapper.updateById(B);","        if (result == 1) {","            System.out.println(\"B管理员修改成功!\");","        } else {","            System.out.println(\"B管理员修改失败!\");","        }","        // A管理员后修改","        A.setPrice(8500);","        int result2 = shopMapper.updateById(A);","        if (result2 == 1) {","            System.out.println(\"A管理员修改成功!\");","        } else {","            System.out.println(\"A管理员修改失败!\");","        }","        // 最后查询","        System.out.println(shopMapper.selectById(1L));","    }","}","```","","执行结果：","","```java","B管理员修改成功!","A管理员修改成功!","Shop(id=1, name=笔记本电脑, price=8500, version=1)","```","","**问题出现了，B 管理员的操作被 A 管理员覆盖，那么该如何解决这一问题呢？**","","其实 `MyBatisPlus` 已经提供了乐观锁机制，只需要在实体类中使用 `@Version` 声明版本号属性：","","```java","@Data","public class Shop {","","    private Long id;","    private String name;","    private Integer price;","    @Version // 声明版本号属性","    private Integer version;","}","```","","然后注册乐观锁插件：","","```java","@Configuration","public class MyBatisConfig {","","    /**","     * 注册插件","     * @return","     */","    @Bean","    public MybatisPlusInterceptor mybatisPlusInterceptor() {","        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();","        // 分页插件","        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));","        // 乐观锁插件","        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());","        return interceptor;","    }","}","```","","重新执行测试代码，结果如下：","","```java","B管理员修改成功!","A管理员修改失败!","Shop(id=1, name=笔记本电脑, price=9000, version=2)","```","","此时 A 管理员的修改就失败了，它需要重新读取最新的数据才能再次进行修改。","","## 条件构造器","","在分页插件中我们简单地使用了一下条件构造器（`Wrapper`），下面我们来详细了解一下。","先来看看 `Wrapper` 的继承体系：","![](https://img-blog.csdnimg.cn/20210519083944315.png)","分别介绍一下它们的作用：","","- `Wrapper`：条件构造器抽象类，最顶端的父类","  - `AbstractWrapper`：查询条件封装抽象类，生成 SQL 的 where 条件","    - `QueryWrapper`：用于对象封装","    - `UpdateWrapper`：用于条件封装","  - `AbstractLambdaWrapper`：Lambda 语法使用 Wrapper","    - `LambdaQueryWrapper`：用于对象封装，使用 Lambda 语法","    - `LambdaUpdateWrapper`：用于条件封装，使用 Lambda 语法","","通常我们使用的都是 `QueryWrapper` 和 `UpdateWrapper`，若是想使用 Lambda 语法来编写，也可以使用 `LambdaQueryWrapper` 和 `LambdaUpdateWrapper`，通过这些条件构造器，我们能够很方便地来实现一些复杂的筛选操作，比如：","","```java","@SpringBootTest","@MapperScan(\"com.wwj.mybatisplusdemo.mapper\")","class MybatisplusDemoApplicationTests {","","    @Autowired","    private EmployeeMapper employeeMapper;","","    @Test","    void contextLoads() {","        // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息","        QueryWrapper\u003cEmployee\u003e wrapper = new QueryWrapper\u003c\u003e();","        wrapper.like(\"last_name\", \"j\");","        wrapper.gt(\"age\", 20);","        wrapper.isNotNull(\"email\");","        List\u003cEmployee\u003e list = employeeMapper.selectList(wrapper);","        list.forEach(System.out::println);","    }","}","```","","运行结果：","","```java","Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)","```","","条件构造器提供了丰富的条件方法帮助我们进行条件的构造，比如 `like` 方法会为我们建立模糊查询，查看一下控制台输出的 SQL：","","```sql","==\u003e  Preparing: SELECT id,last_name,email,age,gmt_create,gmt_modified,is_deleted AS deleted FROM tbl_employee WHERE is_deleted=0 AND (last_name LIKE ? AND age \u003e ? AND email IS NOT NULL)","==\u003e Parameters: %j%(String), 20(Integer)","```","","可以看到它是对 `j` 的前后都加上了 `%` ，若是只想查询以 `j` 开头的名字，则可以使用 `likeRight` 方法，若是想查询以 `j` 结尾的名字，，则使用 `likeLeft` 方法。","","年龄的比较也是如此， `gt` 是大于指定值，若是小于则调用 `lt` ，大于等于调用 `ge` ，小于等于调用 `le` ，不等于调用 `ne` ，还可以使用 `between` 方法实现这一过程，相关的其它方法都可以查阅源码进行学习。","","因为这些方法返回的其实都是自身实例，所以可使用链式编程：","","```java","@Test","void contextLoads() {","    // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息","    QueryWrapper\u003cEmployee\u003e wrapper = new QueryWrapper\u003cEmployee\u003e()","        .likeLeft(\"last_name\", \"j\")","        .gt(\"age\", 20)","        .isNotNull(\"email\");","    List\u003cEmployee\u003e list = employeeMapper.selectList(wrapper);","    list.forEach(System.out::println);","}","```","","也可以使用 `LambdaQueryWrapper` 实现：","","```java","@Test","void contextLoads() {","    // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息","    LambdaQueryWrapper\u003cEmployee\u003e wrapper = new LambdaQueryWrapper\u003cEmployee\u003e()","        .like(Employee::getLastName,\"j\")","        .gt(Employee::getAge,20)","        .isNotNull(Employee::getEmail);","    List\u003cEmployee\u003e list = employeeMapper.selectList(wrapper);","    list.forEach(System.out::println);","}","```","","这种方式的好处在于对字段的设置不是硬编码，而是采用方法引用的形式，效果与 `QueryWrapper` 是一样的。","","`UpdateWrapper` 与 `QueryWrapper` 不同，它的作用是封装更新内容的，比如：","","```java","@Test","void contextLoads() {","    UpdateWrapper\u003cEmployee\u003e wrapper = new UpdateWrapper\u003cEmployee\u003e()","        .set(\"age\", 50)","        .set(\"email\", \"emp@163.com\")","        .like(\"last_name\", \"j\")","        .gt(\"age\", 20);","    employeeMapper.update(null, wrapper);","}","```","","将名字中包含 `j` 且年龄大于 20 岁的员工年龄改为 50，邮箱改为 emp@163.com，`UpdateWrapper` 不仅能够封装更新内容，也能作为查询条件，所以在更新数据时可以直接构造一个 `UpdateWrapper` 来设置更新内容和条件。"],"stylingDirectives":[[[0,1,"pl-s"],[1,8,"pl-c1"],[8,9,"pl-s"],[60,61,"pl-s"],[61,72,"pl-c1"],[72,73,"pl-s"],[78,79,"pl-s"],[79,86,"pl-c1"],[86,87,"pl-s"],[122,123,"pl-s"],[123,134,"pl-c1"],[134,135,"pl-s"]],[],[[0,43,"pl-ent"],[0,2,"pl-ent"],[15,16,"pl-s"],[16,23,"pl-c1"],[23,24,"pl-s"],[27,28,"pl-s"],[28,39,"pl-c1"],[39,40,"pl-s"]],[[0,0,"pl-ent"]],[[20,41,"pl-corl"]],[],[[0,7,"pl-mh"],[3,7,"pl-en"]],[],[[3,4,"pl-s"],[4,15,"pl-c1"],[15,16,"pl-s"]],[],[[0,2,"pl-s"],[32,34,"pl-s"]],[],[[0,3,"pl-s"],[3,6,"pl-en"]],[[1,11,"pl-ent"]],[[3,10,"pl-ent"],[25,32,"pl-ent"]],[[3,13,"pl-ent"],[41,51,"pl-ent"]],[[3,10,"pl-ent"],[18,25,"pl-ent"]],[[2,12,"pl-ent"]],[[1,11,"pl-ent"]],[[3,10,"pl-ent"],[18,25,"pl-ent"]],[[3,13,"pl-ent"],[36,46,"pl-ent"]],[[3,8,"pl-ent"],[18,23,"pl-ent"]],[[2,12,"pl-ent"]],[[1,11,"pl-ent"]],[[3,10,"pl-ent"],[30,37,"pl-ent"]],[[3,13,"pl-ent"],[22,32,"pl-ent"]],[[2,12,"pl-ent"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[12,14,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-ent"]],[[2,12,"pl-ent"]],[[4,21,"pl-ent"],[23,47,"pl-s"]],[[4,12,"pl-ent"],[14,18,"pl-s"]],[[4,7,"pl-ent"],[9,53,"pl-s"]],[[4,12,"pl-ent"],[14,20,"pl-c1"]],[[0,3,"pl-s"],[0,1,"pl-pds"],[1,2,"pl-pds"],[2,3,"pl-pds"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,0,"pl-s"]],[[0,3,"pl-s"],[0,1,"pl-pds"],[1,2,"pl-pds"],[2,3,"pl-pds"],[3,6,"pl-s"]],[[0,30,"pl-s"]],[],[[0,18,"pl-s"]],[],[[0,36,"pl-s"]],[],[[0,29,"pl-s"]],[[2,6,"pl-s"],[2,3,"pl-pds"],[5,6,"pl-pds"],[7,27,"pl-s"]],[[2,13,"pl-s"],[2,3,"pl-pds"],[12,13,"pl-pds"],[14,40,"pl-s"]],[[2,9,"pl-s"],[2,3,"pl-pds"],[8,9,"pl-pds"],[10,36,"pl-s"]],[[2,10,"pl-s"],[2,3,"pl-pds"],[9,10,"pl-pds"],[11,32,"pl-s"]],[[2,7,"pl-s"],[2,3,"pl-pds"],[6,7,"pl-pds"],[8,29,"pl-s"]],[[2,20,"pl-s"]],[[0,53,"pl-s"]],[],[[0,172,"pl-s"]],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[13,15,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,5,"pl-k"]],[[0,6,"pl-k"],[7,12,"pl-k"],[13,21,"pl-en"]],[],[[4,11,"pl-k"],[12,16,"pl-smi"]],[[4,11,"pl-k"],[12,18,"pl-smi"]],[[4,11,"pl-k"],[12,18,"pl-smi"]],[[4,11,"pl-k"],[12,19,"pl-smi"]],[],[[0,3,"pl-s"]],[],[[0,2,"pl-s"],[7,8,"pl-s"],[8,14,"pl-c1"],[14,15,"pl-s"],[19,21,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,6,"pl-k"],[7,16,"pl-k"],[17,31,"pl-en"],[32,39,"pl-k"],[40,60,"pl-e"],[51,59,"pl-smi"]],[],[[0,3,"pl-s"]],[],[[7,8,"pl-s"],[8,19,"pl-c1"],[19,20,"pl-s"],[25,26,"pl-s"],[26,36,"pl-c1"],[36,37,"pl-s"],[53,54,"pl-s"],[54,62,"pl-c1"],[62,63,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,15,"pl-k"]],[[0,11,"pl-k"],[12,44,"pl-s"],[12,13,"pl-pds"],[43,44,"pl-pds"]],[[0,5,"pl-k"],[6,37,"pl-en"]],[],[[4,14,"pl-k"]],[[4,11,"pl-k"],[12,26,"pl-smi"]],[],[[4,9,"pl-k"]],[[4,8,"pl-k"],[9,21,"pl-en"]],[[8,22,"pl-k"],[13,21,"pl-smi"],[33,34,"pl-k"],[49,50,"pl-k"],[61,65,"pl-c1"]],[[17,18,"pl-k"],[26,32,"pl-smi"],[32,33,"pl-k"],[36,38,"pl-k"]],[],[],[[0,3,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[0,47,"pl-smi"],[24,25,"pl-k"],[47,48,"pl-k"]],[[4,9,"pl-smi"],[30,35,"pl-smi"],[35,36,"pl-k"],[37,69,"pl-smi"],[45,46,"pl-k"],[69,70,"pl-k"],[71,76,"pl-smi"],[77,99,"pl-s"],[77,78,"pl-pds"],[98,99,"pl-pds"],[105,113,"pl-s"],[105,106,"pl-pds"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,140,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,35,"pl-s"]],[[0,23,"pl-s"]],[[0,0,"pl-s"]],[[0,20,"pl-s"]],[[0,28,"pl-s"]],[[0,25,"pl-s"]],[[0,24,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,56,"pl-s"]],[[0,54,"pl-s"]],[[0,58,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,28,"pl-s"]],[[0,0,"pl-s"]],[[0,54,"pl-s"]],[[0,0,"pl-s"]],[[0,31,"pl-s"]],[[0,0,"pl-s"]],[[0,81,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,61,"pl-s"]],[[0,1,"pl-s"]],[[0,0,"pl-s"]],[[0,8,"pl-s"]],[[0,107,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,106,"pl-s"]],[[0,0,"pl-s"]],[[0,170,"pl-s"]],[[0,0,"pl-s"]],[[0,38,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,15,"pl-s"]],[[0,45,"pl-s"]],[[0,39,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,44,"pl-s"]],[[0,0,"pl-s"]],[[0,9,"pl-s"]],[[0,25,"pl-s"]],[[0,53,"pl-s"]],[[0,42,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,56,"pl-s"]],[[0,54,"pl-s"]],[[0,58,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,55,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,62,"pl-s"]],[[0,0,"pl-s"]],[[0,75,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,89,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,16,"pl-s"]],[[0,51,"pl-s"]],[[0,54,"pl-s"]],[[0,0,"pl-s"]],[[0,66,"pl-s"]],[[0,0,"pl-s"]],[[0,26,"pl-s"]],[[0,41,"pl-s"]],[[0,10,"pl-s"]],[[0,0,"pl-s"]],[[0,88,"pl-s"]],[[0,45,"pl-s"]],[[0,25,"pl-s"]],[[0,37,"pl-s"]],[[0,13,"pl-s"]],[[0,9,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,50,"pl-s"]],[[0,0,"pl-s"]],[[0,54,"pl-s"]],[[0,0,"pl-s"]],[[0,58,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,39,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,39,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,61,"pl-s"]],[[0,0,"pl-s"]],[[0,54,"pl-s"]],[[0,1,"pl-s"]],[[0,0,"pl-s"]],[[0,8,"pl-s"]],[[0,107,"pl-s"]],[[0,0,"pl-s"]],[[0,13,"pl-s"]],[[0,62,"pl-s"]],[[0,56,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,92,"pl-s"]],[[0,0,"pl-s"]],[[0,53,"pl-s"]],[[0,0,"pl-s"]],[[0,118,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,15,"pl-s"]],[[0,45,"pl-s"]],[[0,39,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,44,"pl-s"]],[[0,0,"pl-s"]],[[0,9,"pl-s"]],[[0,25,"pl-s"]],[[0,71,"pl-s"]],[[0,42,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,54,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,8,"pl-s"]],[[0,0,"pl-s"]],[[0,45,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,39,"pl-s"]],[[0,33,"pl-s"]],[[0,37,"pl-s"]],[[0,24,"pl-s"]],[[0,35,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,13,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,34,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,66,"pl-s"]],[[0,24,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,57,"pl-s"]],[[0,0,"pl-s"]],[[0,129,"pl-s"]],[[0,0,"pl-s"]],[[0,170,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,12,"pl-s"]],[[0,9,"pl-s"]],[[0,15,"pl-s"]],[[0,7,"pl-s"]],[[0,9,"pl-s"]],[[0,9,"pl-s"]],[[0,0,"pl-s"]],[[0,110,"pl-s"]],[[0,0,"pl-s"]],[[0,104,"pl-s"]],[[0,0,"pl-s"]],[[0,37,"pl-s"]],[[0,59,"pl-s"]],[[0,91,"pl-s"]],[[0,108,"pl-s"]],[[0,0,"pl-s"]],[[0,81,"pl-s"]],[[0,0,"pl-s"]],[[0,63,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,26,"pl-s"]],[[0,23,"pl-s"]],[[0,0,"pl-s"]],[[0,42,"pl-s"]],[[0,20,"pl-s"]],[[0,28,"pl-s"]],[[0,25,"pl-s"]],[[0,24,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,25,"pl-s"]],[[0,54,"pl-s"]],[[0,115,"pl-s"]],[[0,0,"pl-s"]],[[0,131,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,52,"pl-s"]],[[0,16,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,19,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,16,"pl-s"]],[[0,14,"pl-s"]],[[0,19,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,22,"pl-s"]],[[0,0,"pl-s"]],[[0,9,"pl-s"]],[[0,0,"pl-s"]],[[0,44,"pl-s"]],[[0,54,"pl-s"]],[[0,18,"pl-s"]],[[0,0,"pl-s"]],[[0,13,"pl-s"]],[[0,30,"pl-s"]],[[0,27,"pl-s"]],[[0,0,"pl-s"]],[[0,10,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,65,"pl-s"]],[[0,67,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,10,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,26,"pl-s"]],[[0,23,"pl-s"]],[[0,0,"pl-s"]],[[0,42,"pl-s"]],[[0,20,"pl-s"]],[[0,28,"pl-s"]],[[0,25,"pl-s"]],[[0,24,"pl-s"]],[[0,36,"pl-s"]],[[0,38,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,31,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,39,"pl-s"]],[[0,33,"pl-s"]],[[0,37,"pl-s"]],[[0,24,"pl-s"]],[[0,13,"pl-s"]],[[0,47,"pl-s"]],[[0,49,"pl-s"]],[[0,35,"pl-s"]],[[0,1,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,39,"pl-s"]],[[0,41,"pl-s"]],[[0,24,"pl-s"]],[[0,13,"pl-s"]],[[0,49,"pl-s"]],[[0,41,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,82,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,26,"pl-s"]],[[0,23,"pl-s"]],[[0,0,"pl-s"]],[[0,32,"pl-s"]],[[0,20,"pl-s"]],[[0,28,"pl-s"]],[[0,25,"pl-s"]],[[0,24,"pl-s"]],[[0,53,"pl-s"]],[[0,36,"pl-s"]],[[0,63,"pl-s"]],[[0,38,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,31,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,10,"pl-s"]],[[0,6,"pl-s"]],[[0,63,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,17,"pl-s"]],[[0,24,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,51,"pl-s"]],[[0,33,"pl-s"]],[[0,95,"pl-s"]],[[0,97,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,17,"pl-s"]],[[0,24,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,51,"pl-s"]],[[0,33,"pl-s"]],[[0,97,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,78,"pl-s"]],[[0,0,"pl-s"]],[[0,27,"pl-s"]],[[0,26,"pl-s"]],[[0,20,"pl-s"]],[[0,22,"pl-s"]],[[0,0,"pl-s"]],[[0,48,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,39,"pl-s"]],[[0,41,"pl-s"]],[[0,24,"pl-s"]],[[0,41,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,88,"pl-s"]],[[0,127,"pl-s"]],[[0,132,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,85,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,10,"pl-s"]],[[0,6,"pl-s"]],[[0,63,"pl-s"]],[[0,0,"pl-s"]],[[0,13,"pl-s"]],[[0,51,"pl-s"]],[[0,65,"pl-s"]],[[0,69,"pl-s"]],[[0,27,"pl-s"]],[[0,79,"pl-s"]],[[0,36,"pl-s"]],[[0,105,"pl-s"]],[[0,13,"pl-s"]],[[0,9,"pl-s"]],[[0,29,"pl-s"]],[[0,83,"pl-s"]],[[0,38,"pl-s"]],[[0,107,"pl-s"]],[[0,13,"pl-s"]],[[0,9,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,13,"pl-s"]],[[0,51,"pl-s"]],[[0,69,"pl-s"]],[[0,29,"pl-s"]],[[0,83,"pl-s"]],[[0,38,"pl-s"]],[[0,107,"pl-s"]],[[0,13,"pl-s"]],[[0,9,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,0,"pl-s"]],[[0,25,"pl-s"]],[[0,0,"pl-s"]],[[0,58,"pl-s"]],[[0,46,"pl-s"]],[[0,0,"pl-s"]],[[0,122,"pl-s"]],[[0,0,"pl-s"]],[[0,54,"pl-s"]],[[0,0,"pl-s"]],[[0,64,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,64,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,26,"pl-s"]],[[0,23,"pl-s"]],[[0,0,"pl-s"]],[[0,32,"pl-s"]],[[0,20,"pl-s"]],[[0,28,"pl-s"]],[[0,25,"pl-s"]],[[0,24,"pl-s"]],[[0,40,"pl-s"]],[[0,36,"pl-s"]],[[0,47,"pl-s"]],[[0,38,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,7,"pl-s"]],[[0,15,"pl-s"]],[[0,29,"pl-s"]],[[0,28,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,53,"pl-s"]],[[0,0,"pl-s"]],[[0,177,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,34,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,34,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,123,"pl-s"]],[[0,24,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,56,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,49,"pl-s"]],[[0,38,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,135,"pl-s"]],[[0,133,"pl-s"]],[[0,153,"pl-s"]],[[0,153,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,72,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,16,"pl-s"]],[[0,67,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,128,"pl-s"]],[[0,15,"pl-s"]],[[0,76,"pl-s"]],[[0,85,"pl-s"]],[[0,83,"pl-s"]],[[0,103,"pl-s"]],[[0,103,"pl-s"]],[[0,17,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,68,"pl-s"]],[[0,37,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,16,"pl-s"]],[[0,14,"pl-s"]],[[0,19,"pl-s"]],[[0,43,"pl-s"]],[[0,34,"pl-s"]],[[0,38,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,38,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,0,"pl-s"]],[[0,44,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,14,"pl-s"]],[[0,28,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,14,"pl-s"]],[[0,7,"pl-s"]],[[0,9,"pl-s"]],[[0,60,"pl-s"]],[[0,74,"pl-s"]],[[0,86,"pl-s"]],[[0,27,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,21,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,42,"pl-s"]],[[0,37,"pl-s"]],[[0,52,"pl-s"]],[[0,46,"pl-s"]],[[0,51,"pl-s"]],[[0,54,"pl-s"]],[[0,51,"pl-s"]],[[0,56,"pl-s"]],[[0,55,"pl-s"]],[[0,51,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,56,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,131,"pl-s"]],[[0,129,"pl-s"]],[[0,7,"pl-s"]],[[0,8,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,12,"pl-s"]],[[0,11,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,42,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,43,"pl-s"]],[[0,59,"pl-s"]],[[0,48,"pl-s"]],[[0,43,"pl-s"]],[[0,52,"pl-s"]],[[0,46,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,58,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,0,"pl-s"]],[[0,251,"pl-s"]],[[0,0,"pl-s"]],[[0,27,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,6,"pl-s"]],[[0,0,"pl-s"]],[[0,79,"pl-s"]],[[0,0,"pl-s"]],[[0,121,"pl-s"]],[[0,0,"pl-s"]],[[0,165,"pl-s"]],[[0,0,"pl-s"]],[[0,92,"pl-s"]],[[0,0,"pl-s"]],[[0,54,"pl-s"]],[[0,0,"pl-s"]],[[0,43,"pl-s"]],[[0,0,"pl-s"]],[[0,16,"pl-s"]],[[0,0,"pl-s"]],[[0,16,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,18,"pl-s"]],[[0,39,"pl-s"]],[[0,28,"pl-s"]],[[0,26,"pl-s"]],[[0,28,"pl-s"]],[[0,17,"pl-s"]],[[0,2,"pl-s"]],[[0,0,"pl-s"]],[[0,42,"pl-s"],[41,42,"pl-pds"],[47,55,"pl-s"],[47,48,"pl-pds"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,12,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,19,"pl-s"]],[[0,0,"pl-s"]],[[0,20,"pl-s"]],[[0,24,"pl-s"]],[[0,26,"pl-s"]],[[0,28,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,24,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,54,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,13,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,15,"pl-s"]],[[0,45,"pl-s"]],[[0,39,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,34,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,13,"pl-s"]],[[0,7,"pl-s"]],[[0,9,"pl-s"]],[[0,25,"pl-s"]],[[0,21,"pl-s"]],[[0,43,"pl-s"]],[[0,43,"pl-s"]],[[0,18,"pl-s"]],[[0,25,"pl-s"]],[[0,46,"pl-s"]],[[0,26,"pl-s"]],[[0,44,"pl-s"]],[[0,16,"pl-s"]],[[0,44,"pl-s"]],[[0,9,"pl-s"]],[[0,18,"pl-s"]],[[0,25,"pl-s"]],[[0,47,"pl-s"]],[[0,27,"pl-s"]],[[0,44,"pl-s"]],[[0,16,"pl-s"]],[[0,44,"pl-s"]],[[0,9,"pl-s"]],[[0,15,"pl-s"]],[[0,54,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,9,"pl-s"]],[[0,9,"pl-s"]],[[0,45,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,41,"pl-s"]],[[0,0,"pl-s"]],[[0,58,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,19,"pl-s"]],[[0,0,"pl-s"]],[[0,20,"pl-s"]],[[0,24,"pl-s"]],[[0,26,"pl-s"]],[[0,23,"pl-s"]],[[0,28,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,10,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,14,"pl-s"]],[[0,28,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,11,"pl-s"]],[[0,14,"pl-s"]],[[0,7,"pl-s"]],[[0,9,"pl-s"]],[[0,60,"pl-s"]],[[0,74,"pl-s"]],[[0,15,"pl-s"]],[[0,86,"pl-s"]],[[0,16,"pl-s"]],[[0,80,"pl-s"]],[[0,27,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,9,"pl-s"]],[[0,9,"pl-s"]],[[0,45,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,37,"pl-s"]],[[0,0,"pl-s"]],[[0,8,"pl-s"]],[[0,0,"pl-s"]],[[0,45,"pl-s"]],[[0,21,"pl-s"]],[[0,54,"pl-s"]],[[0,12,"pl-s"]],[[0,0,"pl-s"]],[[0,27,"pl-s"]],[[0,49,"pl-s"]],[[0,27,"pl-s"]],[[0,28,"pl-s"]],[[0,47,"pl-s"]],[[0,46,"pl-s"]],[[0,47,"pl-s"]],[[0,0,"pl-s"]],[[0,147,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,15,"pl-s"]],[[0,45,"pl-s"]],[[0,39,"pl-s"]],[[0,0,"pl-s"]],[[0,14,"pl-s"]],[[0,42,"pl-s"]],[[0,0,"pl-s"]],[[0,9,"pl-s"]],[[0,25,"pl-s"]],[[0,19,"pl-s"],[18,19,"pl-pds"],[20,40,"pl-s"],[20,21,"pl-pds"]],[[0,62,"pl-s"]],[[0,39,"pl-s"]],[[0,30,"pl-s"]],[[0,35,"pl-s"]],[[0,65,"pl-s"]],[[0,42,"pl-s"]],[[0,5,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,5,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,131,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,65,"pl-s"]],[[0,0,"pl-s"]],[[0,6,"pl-s"]],[[0,185,"pl-s"]],[[0,40,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,100,"pl-s"]],[[0,0,"pl-s"]],[[0,119,"pl-s"]],[[0,0,"pl-s"]],[[0,28,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,15,"pl-s"],[14,15,"pl-pds"],[16,36,"pl-s"],[16,17,"pl-pds"]],[[0,65,"pl-s"]],[[0,35,"pl-s"]],[[0,22,"pl-s"]],[[0,28,"pl-s"]],[[0,61,"pl-s"]],[[0,38,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,30,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,15,"pl-s"],[14,15,"pl-pds"],[16,36,"pl-s"],[16,17,"pl-pds"]],[[0,77,"pl-s"]],[[0,40,"pl-s"]],[[0,32,"pl-s"]],[[0,39,"pl-s"]],[[0,61,"pl-s"]],[[0,38,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,57,"pl-s"]],[[0,0,"pl-s"]],[[0,52,"pl-s"]],[[0,0,"pl-s"]],[[0,7,"pl-s"]],[[0,5,"pl-s"]],[[0,21,"pl-s"]],[[0,67,"pl-s"]],[[0,23,"pl-s"]],[[0,36,"pl-s"]],[[0,31,"pl-s"]],[[0,23,"pl-s"]],[[0,41,"pl-s"]],[[0,1,"pl-s"]],[[0,3,"pl-s"]],[[0,0,"pl-s"]],[[0,129,"pl-s"]]],"colorizedLines":null}},"title":"springboot-guide/docs/MyBatisPlus.md at master · CodingDocs/springboot-guide","appPayload":{},"meta":{"title":"springboot-guide/docs/MyBatisPlus.md at master · CodingDocs/springboot-guide"}}</script>
  <div data-target="react-app.reactRoot"><meta name="github-code-view-meta-stats" id="github-code-view-meta-stats" data-hydrostats="publish"/> <!-- --> <a hidden="" id="code-view-repo-link" href="/CodingDocs/springboot-guide" data-discover="true"></a> <div class="d-none"></div><div><div style="--spacing:var(--spacing-none)" class="prc-PageLayout-PageLayoutRoot--KH-d" data-component="SplitPageLayout" data-has-sidebar="true"><div class="prc-PageLayout-SidebarWrapper-kLG4B CopilotSidePanelSidebar-module__SidePanel__L3O0C CopilotSidePanelSidebar-module__HiddenSidePanel__TBRGn" style="--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="end" data-sticky="true" data-responsive-variant="fullscreen"><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-SidebarVerticalDivider-0Rl0V" data-component="PageLayout.VerticalDivider" data-variant="line" data-position="end" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="450" aria-valuemax="768" aria-valuenow="544" aria-valuetext="Pane width 544 pixels" tabindex="0"></div></div><div class="prc-PageLayout-Sidebar-iciWg" data-component="SplitPageLayout.Sidebar" data-resizable="true" style="--spacing:var(--spacing-normal);--pane-min-width:450px;--pane-max-width:768px;--pane-width-custom:544px;--pane-width-size:var(--pane-width-custom);--pane-width:544px"><div class="height-full" data-testid="copilot-code-view-side-panel"><div id="copilot-side-panel-content" class="height-full"></div></div></div></div><div class="prc-PageLayout-PageLayoutWrapper-2BhU2" data-width="full"><div class="prc-PageLayout-PageLayoutContent-BneH9"><div id="repos-file-tree-sidebar" class="CodeViewFileTreeLayout-module__sidebar__n_Aau" tabindex="0"><div class="prc-PageLayout-PaneWrapper-pHPop ReposFileTreePane-module__Pane__rBZpI ReposFileTreePane-module__HideTree__AYZnm ReposFileTreePane-module__HidePane__VHAVt" style="--offset-header:0px;--spacing-row:var(--spacing-none);--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="start" data-sticky="true"><div class="prc-PageLayout-HorizontalDivider-JLVqp prc-PageLayout-PaneHorizontalDivider-9tbnE" data-component="PageLayout.HorizontalDivider" data-variant-regular="none" data-variant-narrow="none" data-position="start" style="--spacing-divider:var(--spacing-none);--spacing:var(--spacing-none)"></div><div class="prc-PageLayout-Pane-AyzHK" data-component="SplitPageLayout.Pane" data-resizable="true" style="--spacing:var(--spacing-none);--pane-min-width:256px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));--pane-width-size:var(--pane-width-large);--pane-width:320px"></div><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-PaneVerticalDivider-le57g" data-component="PageLayout.VerticalDivider" data-variant-narrow="none" data-variant-regular="line" data-variant-wide="line" data-position="start" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="256" aria-valuemax="600" aria-valuenow="320" aria-valuetext="Pane width 320 pixels" tabindex="0"></div></div></div></div><div data-component="SplitPageLayout.Content" class="prc-PageLayout-ContentWrapper-gR9eG"><div class="prc-PageLayout-Content-xWL-A" data-width="full" style="--spacing:var(--spacing-none)"><div class="SharedPageLayout-module__content__IwGAp" data-selector="repos-split-pane-content" id="repos-split-pane-content" tabindex="0"> <!-- --> <div class="container CodeViewHeader-module__Box__JkPOb"><div class="CodeViewHeader-module__StickyHeader__Qn7UN" id="StickyHeader"><div class="CodeViewHeader-module__Box_1__SbNDV"><div class="CodeViewHeader-module__Box_2__TB46f"><div class="react-code-view-header-wrap--narrow CodeViewHeader-module__Box_3__q1zUL"><div class="CodeViewHeader-module__treeToggleWrapper__RQ__9"><h2 class="use-tree-pane-module__Heading__s4QbZ prc-Heading-Heading-MtWFE" data-component="Heading"><button data-component="Button" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="prc-Button-ButtonBase-9n-Xk ExpandFileTreeButton-module__Button_1__Svs95" data-loading="false" data-size="medium" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Files</span></span></button><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-9n-Xk position-relative ExpandFileTreeButton-module__expandButton__hDOcv ExpandFileTreeButton-module__filesButtonBreakpoint__zEvz3 fgColor-muted prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-labelledby="_R_4lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="se" data-component="Tooltip" aria-hidden="true" id="_R_4lla9lik5_">Expand file tree</span><div class="d-none"></div></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="master branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">master</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="react-code-view-header-mb--narrow CodeViewHeader-module__Box_5__MQ0hL"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__lg__Rjz0A"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/CodingDocs/springboot-guide/tree/master" data-discover="true">springboot-guide</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/CodingDocs/springboot-guide/tree/master/docs" data-discover="true">docs</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__lg__Rjz0A prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="file-name-id">MyBatisPlus.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lla9lik5_">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><div><div class="CodeViewHeader-module__FileResultsList__JDzUy"><span class="d-flex FileResultsList-module__FilesSearchBox__ivVkc TextInput-wrapper prc-components-TextInputWrapper-Hpdqi prc-components-TextInputBaseWrapper-wY-n0" data-no-trailing-action="true" data-component="TextInput" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id="_R_5ipla9lik5_" aria-hidden="true" data-component="TextInput.LeadingVisual"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellCheck="false" placeholder="Go to file" aria-describedby="_R_5ipla9lik5_ _R_5ipla9lik5H1_" data-component="input" class="prc-components-Input-IwWrt" value=""/><span class="TextInput-icon" id="_R_5ipla9lik5H1_" aria-hidden="true" data-component="TextInput.TrailingVisual"></span></span></div><div class="d-none"></div></div><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_v4pla9lik5_" id="_R_14pla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_v4pla9lik5_">More file actions</span></div></div></div><div class="react-code-view-header-element--narrow"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_v4tla9lik5_" id="_R_14tla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_v4tla9lik5_">More file actions</span></div></div></div></div></div></div></div><div class="CodeView-module__contentWrapper__cG2JH"><div class="react-code-view-bottom-padding"><div class="BlobTopBanners-module__Box__v_nvx"></div></div> <div class="d-none"></div><div class="d-flex flex-column border rounded-2 tmp-mb-3 pl-1"><div class="LatestCommit-module__Box__B25ZT"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">History</h2><a data-component="LinkButton" href="/CodingDocs/springboot-guide/commits/master/docs/MyBatisPlus.md" class="prc-Button-ButtonBase-9n-Xk d-none d-lg-flex LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><a data-component="LinkButton" aria-label="View commit history for this file." href="/CodingDocs/springboot-guide/commits/master/docs/MyBatisPlus.md" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby="_R_4mlala9lik5_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" role="tooltip" aria-hidden="true" id="_R_4mlala9lik5_">History</span></div></div></div></div></div><div class="d-flex flex-row"><div class="container BlobViewContent-module__blobContainer__DtH2d"><div class="react-code-size-details-banner BlobViewContent-module__codeSizeDetails__e5sUw"><div class="react-code-size-details-banner CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="35 KB" style="--truncate-max-width:100%"><span>975 lines (763 loc) · 35 KB</span></div></div></div></div><div class="react-blob-view-header-sticky BlobViewContent-module__stickyHeader__VwxB5" id="repos-sticky-header"><div class="BlobViewHeader-module__Box__yhm9u"><div class="react-blob-sticky-header"><div class="FileNameStickyHeader-module__outerWrapper__ZL4Xc FileNameStickyHeader-module__outerWrapperHidden__Zpynk"><div class="FileNameStickyHeader-module__Box_1__Hazu5"><div class="FileNameStickyHeader-module__Box_2__hoolP"><div class="FileNameStickyHeader-module__Box_3__MVKsk"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="master branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">master</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="FileNameStickyHeader-module__Box_4__FLhtt"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__md__Wb1Gs"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/CodingDocs/springboot-guide/tree/master" data-discover="true">springboot-guide</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/CodingDocs/springboot-guide/tree/master/docs" data-discover="true">docs</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__md__Wb1Gs prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="sticky-file-name-id">MyBatisPlus.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lcpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lcpala9lik5_">Copy path</span></div></div></div><button data-component="Button" type="button" class="prc-Button-ButtonBase-9n-Xk FileNameStickyHeader-module__Button__LSEU_ FileNameStickyHeader-module__GoToTopButton__nxAFn" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Top</span></span></button></div></div></div><div class="BlobViewHeader-module__Box_1__VEmuQ"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">File metadata and controls</h2><div class="BlobViewHeader-module__Box_2__icUs2"><ul aria-label="File view" class="prc-SegmentedControl-SegmentedControl-lqIXp BlobTabButtons-module__SegmentedControl__jen2u" data-variant="default" data-size="small" data-component="SegmentedControl"><li class="prc-SegmentedControl-Item-tSCQh" data-selected="" data-component="SegmentedControl.Button"><button aria-pressed="true" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:transparent"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><div class="d-none"></div><div class="react-code-size-details-in-header CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="35 KB" style="--truncate-max-width:100%"><span>975 lines (763 loc) · 35 KB</span></div></div></div></div><div class="BlobViewHeader-module__Box_3__ng6v2"><div class="d-none"></div><div class="react-blob-header-edit-and-raw-actions BlobViewHeader-module__Box_4__J4Y4W"><div class="d-none"></div><div class="prc-ButtonGroup-ButtonGroup-vFUrY" data-component="ButtonGroup"><div class="prc-ButtonGroup-Item-PqvDl"><a data-component="LinkButton" href="https://github.com/CodingDocs/springboot-guide/raw/refs/heads/master/docs/MyBatisPlus.md" data-testid="raw-button" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov BlobViewHeader-module__LinkButton__X9kx2" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Raw</span></span></a></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="copy-raw-button" class="prc-Button-ButtonBase-9n-Xk prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_qaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_qaucpala9lik5_">Copy raw file</span></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="download-raw-button" class="prc-Button-ButtonBase-9n-Xk BlobViewHeader-module__downloadButton__ef459 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_eaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_eaucpala9lik5_">Download raw file</span></div></div></div><button data-component="IconButton" type="button" aria-pressed="false" class="prc-Button-ButtonBase-9n-Xk tmp-mr-2 TableOfContents-module__IconButton__jrlNM prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_3ucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_3ucpala9lik5_">Outline</span><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click BlobViewHeader-module__IconButton__XrMQY prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_fkecpala9lik5_" id="_R_kecpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_fkecpala9lik5_">Edit and raw actions</span></div></div></div></div><div></div></div><div class="BlobViewContent-module__blobContentWrapper__JS0W6"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="BlobContent-module__blobContentSection__VOgZq BlobContent-module__blobContentSectionMarkdown__mPLOK" style="margin-top:46px"><div class="js-snippet-clipboard-copy-unpositioned BlobContent-module__markdownBlob__T8jpG" data-hpc="true" containertiming="hpc"><article class="markdown-body entry-content container-lg" itemprop="text"><p dir="auto"><code>MyBatis</code> 是一款优秀的持久层框架，它支持定制化 SQL、存储过程以及高级映射，而实际开发中，我们都会选择使用 <code>MyBatisPlus</code>，它是对 <code>MyBatis</code> 框架的进一步增强，能够极大地简化我们的持久层代码，下面就一起来看看 <code>MyBatisPlus</code> 中的一些奇淫巧技吧。</p>
<blockquote>
<p dir="auto">说明：本篇文章需要一定的 <code>MyBatis</code> 与 <code>MyBatisPlus</code> 基础</p>
</blockquote>
<p dir="auto">MyBatis-Plus 官网地址 ： <a href="https://baomidou.com/" rel="nofollow">https://baomidou.com/</a> 。</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">CRUD</h2><a id="user-content-crud" class="anchor" aria-label="Permalink: CRUD" href="#crud"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">使用 <code>MyBatisPlus</code> 实现业务的增删改查非常地简单，一起来看看吧。</p>
<p dir="auto"><strong>1.首先新建一个 SpringBoot 工程，然后引入依赖：</strong></p>
<div class="highlight highlight-text-xml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;dependency&gt;
  &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
  &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
  &lt;version&gt;3.4.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;mysql&lt;/groupId&gt;
  &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
  &lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
  &lt;artifactId&gt;lombok&lt;/artifactId&gt;
&lt;/dependency&gt;"><pre>&lt;<span class="pl-ent">dependency</span>&gt;
  &lt;<span class="pl-ent">groupId</span>&gt;com.baomidou&lt;/<span class="pl-ent">groupId</span>&gt;
  &lt;<span class="pl-ent">artifactId</span>&gt;mybatis-plus-boot-starter&lt;/<span class="pl-ent">artifactId</span>&gt;
  &lt;<span class="pl-ent">version</span>&gt;3.4.2&lt;/<span class="pl-ent">version</span>&gt;
&lt;/<span class="pl-ent">dependency</span>&gt;
&lt;<span class="pl-ent">dependency</span>&gt;
  &lt;<span class="pl-ent">groupId</span>&gt;mysql&lt;/<span class="pl-ent">groupId</span>&gt;
  &lt;<span class="pl-ent">artifactId</span>&gt;mysql-connector-java&lt;/<span class="pl-ent">artifactId</span>&gt;
  &lt;<span class="pl-ent">scope</span>&gt;runtime&lt;/<span class="pl-ent">scope</span>&gt;
&lt;/<span class="pl-ent">dependency</span>&gt;
&lt;<span class="pl-ent">dependency</span>&gt;
  &lt;<span class="pl-ent">groupId</span>&gt;org.projectlombok&lt;/<span class="pl-ent">groupId</span>&gt;
  &lt;<span class="pl-ent">artifactId</span>&gt;lombok&lt;/<span class="pl-ent">artifactId</span>&gt;
&lt;/<span class="pl-ent">dependency</span>&gt;</pre></div>
<p dir="auto"><strong>2.配置一下数据源：</strong></p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    url: jdbc:mysql:///mybatisplus?serverTimezone=UTC
    password: 123456"><pre><span class="pl-ent">spring</span>:
  <span class="pl-ent">datasource</span>:
    <span class="pl-ent">driver-class-name</span>: <span class="pl-s">com.mysql.cj.jdbc.Driver</span>
    <span class="pl-ent">username</span>: <span class="pl-s">root</span>
    <span class="pl-ent">url</span>: <span class="pl-s">jdbc:mysql:///mybatisplus?serverTimezone=UTC</span>
    <span class="pl-ent">password</span>: <span class="pl-c1">123456</span></pre></div>
<p dir="auto"><strong>3.创建一下数据表：</strong></p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="CREATE DATABASE `mybatisplus`;

USE `mybatisplus`;

DROP TABLE IF EXISTS `tbl_employee`;

CREATE TABLE `tbl_employee` (
  `id` bigint(20) NOT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `gender` char(1) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=gbk;

insert  into `tbl_employee`(`id`,`last_name`,`email`,`gender`,`age`) values (1,'jack','jack@qq.com','1',35),(2,'tom','tom@qq.com','1',30),(3,'jerry','jerry@qq.com','1',40);"><pre><span class="pl-k">CREATE</span> <span class="pl-k">DATABASE</span> `<span class="pl-en">mybatisplus</span>`;

USE <span class="pl-s"><span class="pl-pds">`</span>mybatisplus<span class="pl-pds">`</span></span>;

<span class="pl-k">DROP</span> <span class="pl-k">TABLE</span> IF EXISTS <span class="pl-s"><span class="pl-pds">`</span>tbl_employee<span class="pl-pds">`</span></span>;

<span class="pl-k">CREATE</span> <span class="pl-k">TABLE</span> `<span class="pl-en">tbl_employee</span>` (
  <span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span> <span class="pl-k">bigint</span>(<span class="pl-c1">20</span>) <span class="pl-k">NOT NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>last_name<span class="pl-pds">`</span></span> <span class="pl-k">varchar</span>(<span class="pl-c1">255</span>) DEFAULT <span class="pl-k">NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>email<span class="pl-pds">`</span></span> <span class="pl-k">varchar</span>(<span class="pl-c1">255</span>) DEFAULT <span class="pl-k">NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>gender<span class="pl-pds">`</span></span> <span class="pl-k">char</span>(<span class="pl-c1">1</span>) DEFAULT <span class="pl-k">NULL</span>,
  <span class="pl-s"><span class="pl-pds">`</span>age<span class="pl-pds">`</span></span> <span class="pl-k">int</span>(<span class="pl-c1">11</span>) DEFAULT <span class="pl-k">NULL</span>,
  <span class="pl-k">PRIMARY KEY</span> (<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>)
) ENGINE<span class="pl-k">=</span>InnoDB AUTO_INCREMENT<span class="pl-k">=</span><span class="pl-c1">8</span> DEFAULT CHARSET<span class="pl-k">=</span>gbk;

<span class="pl-k">insert  into</span> <span class="pl-s"><span class="pl-pds">`</span>tbl_employee<span class="pl-pds">`</span></span>(<span class="pl-s"><span class="pl-pds">`</span>id<span class="pl-pds">`</span></span>,<span class="pl-s"><span class="pl-pds">`</span>last_name<span class="pl-pds">`</span></span>,<span class="pl-s"><span class="pl-pds">`</span>email<span class="pl-pds">`</span></span>,<span class="pl-s"><span class="pl-pds">`</span>gender<span class="pl-pds">`</span></span>,<span class="pl-s"><span class="pl-pds">`</span>age<span class="pl-pds">`</span></span>) <span class="pl-k">values</span> (<span class="pl-c1">1</span>,<span class="pl-s"><span class="pl-pds">'</span>jack<span class="pl-pds">'</span></span>,<span class="pl-s"><span class="pl-pds">'</span>jack@qq.com<span class="pl-pds">'</span></span>,<span class="pl-s"><span class="pl-pds">'</span>1<span class="pl-pds">'</span></span>,<span class="pl-c1">35</span>),(<span class="pl-c1">2</span>,<span class="pl-s"><span class="pl-pds">'</span>tom<span class="pl-pds">'</span></span>,<span class="pl-s"><span class="pl-pds">'</span>tom@qq.com<span class="pl-pds">'</span></span>,<span class="pl-s"><span class="pl-pds">'</span>1<span class="pl-pds">'</span></span>,<span class="pl-c1">30</span>),(<span class="pl-c1">3</span>,<span class="pl-s"><span class="pl-pds">'</span>jerry<span class="pl-pds">'</span></span>,<span class="pl-s"><span class="pl-pds">'</span>jerry@qq.com<span class="pl-pds">'</span></span>,<span class="pl-s"><span class="pl-pds">'</span>1<span class="pl-pds">'</span></span>,<span class="pl-c1">40</span>);</pre></div>
<p dir="auto"><strong>4.创建对应的实体类：</strong></p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
public class Employee {

    private Long id;
    private String lastName;
    private String email;
    private Integer age;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Employee</span> {

    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">email</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">age</span>;
}</pre></div>
<p dir="auto"><strong>4.编写 <code>Mapper</code> 接口：</strong></p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public interface EmployeeMapper extends BaseMapper&lt;Employee&gt; {
}"><pre><span class="pl-k">public</span> <span class="pl-k">interface</span> <span class="pl-smi">EmployeeMapper</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseMapper</span>&lt;<span class="pl-smi">Employee</span>&gt; {
}</pre></div>
<p dir="auto">我们只需继承 <code>MyBatisPlus</code> 提供的 <code>BaseMapper</code> 接口即可，现在我们就拥有了对 <code>Employee</code> 进行增删改查的 API，比如：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@SpringBootTest
@MapperScan(&quot;com.wwj.mybatisplusdemo.mapper&quot;)
class MybatisplusDemoApplicationTests {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Test
    void contextLoads() {
        List&lt;Employee&gt; employees = employeeMapper.selectList(null);
        employees.forEach(System.out::println);
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">SpringBootTest</span>
<span class="pl-c1">@</span><span class="pl-c1">MapperScan</span>(<span class="pl-s">"com.wwj.mybatisplusdemo.mapper"</span>)
<span class="pl-k">class</span> <span class="pl-smi">MybatisplusDemoApplicationTests</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Autowired</span>
    <span class="pl-k">private</span> <span class="pl-smi">EmployeeMapper</span> <span class="pl-s1">employeeMapper</span>;

    <span class="pl-c1">@</span><span class="pl-c1">Test</span>
    <span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
        <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">employees</span> = <span class="pl-s1">employeeMapper</span>.<span class="pl-en">selectList</span>(<span class="pl-c1">null</span>);
        <span class="pl-s1">employees</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
    }
}</pre></div>
<p dir="auto">运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="org.springframework.jdbc.BadSqlGrammarException:
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'mybatisplus.employee' doesn't exist"><pre><span class="pl-smi">org</span>.<span class="pl-smi">springframework</span>.<span class="pl-smi">jdbc</span>.<span class="pl-smi">BadSqlGrammarException</span>:
### <span class="pl-s1">Error</span> <span class="pl-s1">querying</span> <span class="pl-s1">database</span>.  <span class="pl-s1">Cause</span>: <span class="pl-s1">java</span>.<span class="pl-s1">sql</span>.<span class="pl-s1">SQLSyntaxErrorException</span>: <span class="pl-s1">Table</span> <span class="pl-s">'mybatisplus.employee'</span> <span class="pl-s1">doesn</span>'t exist</pre></div>
<p dir="auto">程序报错了，原因是不存在 <code>employee</code> 表，这是因为我们的实体类名为 <code>Employee</code>，<code>MyBatisPlus</code> 默认是以类名作为表名进行操作的，可如果类名和表名不相同（实际开发中也确实可能不同），就需要在实体类中使用 <code>@TableName</code> 注解来声明表的名称：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
@TableName(&quot;tbl_employee&quot;) // 声明表名称
public class Employee {

    private Long id;
    private String lastName;
    private String email;
    private Integer age;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-c1">@</span><span class="pl-c1">TableName</span>(<span class="pl-s">"tbl_employee"</span>) <span class="pl-c">// 声明表名称</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Employee</span> {

    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">email</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">age</span>;
}</pre></div>
<p dir="auto">重新执行测试代码，结果如下：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Employee(id=1, lastName=jack, email=jack@qq.com, age=35)
Employee(id=2, lastName=tom, email=tom@qq.com, age=30)
Employee(id=3, lastName=jerry, email=jerry@qq.com, age=40)"><pre><span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jack</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jack</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">35</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">2</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">tom</span>, <span class="pl-s1">email</span>=<span class="pl-smi">tom</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">30</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">3</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jerry</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jerry</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">40</span>)</pre></div>
<p dir="auto"><code>BaseMapper</code> 提供了常用的一些增删改查方法：</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/24a7bb0b0c749eb3802222eab0c417f092e4e3770995343de1a248ee926a3987/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343035393836352e706e67"><img src="https://camo.githubusercontent.com/24a7bb0b0c749eb3802222eab0c417f092e4e3770995343de1a248ee926a3987/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343035393836352e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210519084059865.png" style="max-width: 100%;"></a></p>
<p dir="auto">具体细节可以查阅其源码自行体会，注释都是中文的，非常容易理解。</p>
<p dir="auto">在开发过程中，我们通常会使用 <code>Service</code> 层来调用 <code>Mapper</code> 层的方法，而 <code>MyBatisPlus</code> 也为我们提供了通用的 <code>Service</code>：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public interface EmployeeService extends IService&lt;Employee&gt; {
}

@Service
public class EmployeeServiceImpl extends ServiceImpl&lt;EmployeeMapper, Employee&gt; implements EmployeeService {
}"><pre><span class="pl-k">public</span> <span class="pl-k">interface</span> <span class="pl-smi">EmployeeService</span> <span class="pl-k">extends</span> <span class="pl-smi">IService</span>&lt;<span class="pl-smi">Employee</span>&gt; {
}

<span class="pl-c1">@</span><span class="pl-c1">Service</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">EmployeeServiceImpl</span> <span class="pl-k">extends</span> <span class="pl-smi">ServiceImpl</span>&lt;<span class="pl-smi">EmployeeMapper</span>, <span class="pl-smi">Employee</span>&gt; <span class="pl-k">implements</span> <span class="pl-smi">EmployeeService</span> {
}</pre></div>
<p dir="auto">事实上，我们只需让 <code>EmployeeServiceImpl</code> 继承 <code>ServiceImpl</code> 即可获得 <code>Service</code> 层的方法，<strong>那么为什么还需要实现 <code>EmployeeService</code> 接口呢？</strong></p>
<p dir="auto">这是因为实现 <code>EmployeeService</code> 接口能够更方便地对业务进行扩展，一些复杂场景下的数据处理，<code>MyBatisPlus</code> 提供的 <code>Service</code> 方法可能无法处理，此时我们就需要自己编写代码，这时候只需在 <code>EmployeeService</code> 中定义自己的方法，并在 <code>EmployeeServiceImpl</code> 中实现即可。</p>
<p dir="auto">先来测试一下 <code>MyBatisPlus</code> 提供的 <code>Service</code> 方法：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@SpringBootTest
@MapperScan(&quot;com.wwj.mybatisplusdemo.mapper&quot;)
class MybatisplusDemoApplicationTests {

    @Autowired
    private EmployeeService employeeService;

    @Test
    void contextLoads() {
        List&lt;Employee&gt; list = employeeService.list();
        list.forEach(System.out::println);
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">SpringBootTest</span>
<span class="pl-c1">@</span><span class="pl-c1">MapperScan</span>(<span class="pl-s">"com.wwj.mybatisplusdemo.mapper"</span>)
<span class="pl-k">class</span> <span class="pl-smi">MybatisplusDemoApplicationTests</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Autowired</span>
    <span class="pl-k">private</span> <span class="pl-smi">EmployeeService</span> <span class="pl-s1">employeeService</span>;

    <span class="pl-c1">@</span><span class="pl-c1">Test</span>
    <span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
        <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">list</span> = <span class="pl-s1">employeeService</span>.<span class="pl-en">list</span>();
        <span class="pl-s1">list</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
    }
}</pre></div>
<p dir="auto">运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Employee(id=1, lastName=jack, email=jack@qq.com, age=35)
Employee(id=2, lastName=tom, email=tom@qq.com, age=30)
Employee(id=3, lastName=jerry, email=jerry@qq.com, age=40)"><pre><span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jack</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jack</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">35</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">2</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">tom</span>, <span class="pl-s1">email</span>=<span class="pl-smi">tom</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">30</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">3</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jerry</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jerry</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">40</span>)</pre></div>
<p dir="auto">接下来模拟一个自定义的场景，我们来编写自定义的操作方法，首先在 <code>EmployeeMapper</code> 中进行声明：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public interface EmployeeMapper extends BaseMapper&lt;Employee&gt; {

    List&lt;Employee&gt; selectAllByLastName(@Param(&quot;lastName&quot;) String lastName);
}"><pre><span class="pl-k">public</span> <span class="pl-k">interface</span> <span class="pl-smi">EmployeeMapper</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseMapper</span>&lt;<span class="pl-smi">Employee</span>&gt; {

    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-en">selectAllByLastName</span>(<span class="pl-c1">@</span><span class="pl-c1">Param</span>(<span class="pl-s">"lastName"</span>) <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>);
}</pre></div>
<p dir="auto">此时我们需要自己编写配置文件实现该方法，在 <code>resource</code> 目录下新建一个 <code>mapper</code> 文件夹，然后在该文件夹下创建 <code>EmployeeMapper.xml</code> 文件：</p>
<div class="highlight highlight-text-xml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;!DOCTYPE mapper
        PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;
        &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&gt;

&lt;mapper namespace=&quot;com.wwj.mybatisplusdemo.mapper.EmployeeMapper&quot;&gt;

    &lt;sql id=&quot;Base_Column&quot;&gt;
        id, last_name, email, gender, age
    &lt;/sql&gt;

    &lt;select id=&quot;selectAllByLastName&quot; resultType=&quot;com.wwj.mybatisplusdemo.bean.Employee&quot;&gt;
        select &lt;include refid=&quot;Base_Column&quot;/&gt;
        from tbl_employee
        where last_name = #{lastName}
    &lt;/select&gt;
&lt;/mapper&gt;"><pre>&lt;!<span class="pl-ent">DOCTYPE</span> <span class="pl-e">mapper</span>
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"&gt;

&lt;<span class="pl-ent">mapper</span> <span class="pl-e">namespace</span>=<span class="pl-s"><span class="pl-pds">"</span>com.wwj.mybatisplusdemo.mapper.EmployeeMapper<span class="pl-pds">"</span></span>&gt;

    &lt;<span class="pl-ent">sql</span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>Base_Column<span class="pl-pds">"</span></span>&gt;
        id, last_name, email, gender, age
    &lt;/<span class="pl-ent">sql</span>&gt;

    &lt;<span class="pl-ent">select</span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>selectAllByLastName<span class="pl-pds">"</span></span> <span class="pl-e">resultType</span>=<span class="pl-s"><span class="pl-pds">"</span>com.wwj.mybatisplusdemo.bean.Employee<span class="pl-pds">"</span></span>&gt;
        select &lt;<span class="pl-ent">include</span> <span class="pl-e">refid</span>=<span class="pl-s"><span class="pl-pds">"</span>Base_Column<span class="pl-pds">"</span></span>/&gt;
        from tbl_employee
        where last_name = #{lastName}
    &lt;/<span class="pl-ent">select</span>&gt;
&lt;/<span class="pl-ent">mapper</span>&gt;</pre></div>
<p dir="auto"><code>MyBatisPlus</code> 默认扫描的是类路径下的 <code>mapper</code> 目录，这可以从源码中得到体现：</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/3a645e2cb6435f646d7175e6fc04931047ec4c3b214d46e7dcd5d71a782d0ec3/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343034363437322e706e67"><img src="https://camo.githubusercontent.com/3a645e2cb6435f646d7175e6fc04931047ec4c3b214d46e7dcd5d71a782d0ec3/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343034363437322e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210519084046472.png" style="max-width: 100%;"></a></p>
<p dir="auto">所以我们直接将 <code>Mapper</code> 配置文件放在该目录下就没有任何问题，可如果不是这个目录，我们就需要进行配置，比如：</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mybatis-plus:
  mapper-locations: classpath:xml/*.xml"><pre><span class="pl-ent">mybatis-plus</span>:
  <span class="pl-ent">mapper-locations</span>: <span class="pl-s">classpath:xml/*.xml</span></pre></div>
<p dir="auto">编写好 <code>Mapper</code> 接口后，我们就需要定义 <code>Service</code> 方法了：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public interface EmployeeService extends IService&lt;Employee&gt; {

    List&lt;Employee&gt; listAllByLastName(String lastName);
}

@Service
public class EmployeeServiceImpl extends ServiceImpl&lt;EmployeeMapper, Employee&gt; implements EmployeeService {

    @Override
    public List&lt;Employee&gt; listAllByLastName(String lastName) {
        return baseMapper.selectAllByLastName(lastName);
    }
}"><pre><span class="pl-k">public</span> <span class="pl-k">interface</span> <span class="pl-smi">EmployeeService</span> <span class="pl-k">extends</span> <span class="pl-smi">IService</span>&lt;<span class="pl-smi">Employee</span>&gt; {

    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-en">listAllByLastName</span>(<span class="pl-smi">String</span> <span class="pl-s1">lastName</span>);
}

<span class="pl-c1">@</span><span class="pl-c1">Service</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">EmployeeServiceImpl</span> <span class="pl-k">extends</span> <span class="pl-smi">ServiceImpl</span>&lt;<span class="pl-smi">EmployeeMapper</span>, <span class="pl-smi">Employee</span>&gt; <span class="pl-k">implements</span> <span class="pl-smi">EmployeeService</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Override</span>
    <span class="pl-k">public</span> <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-en">listAllByLastName</span>(<span class="pl-smi">String</span> <span class="pl-s1">lastName</span>) {
        <span class="pl-k">return</span> <span class="pl-s1">baseMapper</span>.<span class="pl-en">selectAllByLastName</span>(<span class="pl-s1">lastName</span>);
    }
}</pre></div>
<p dir="auto">在 <code>EmployeeServiceImpl</code> 中我们无需将 <code>EmployeeMapper</code> 注入进来，而是使用 <code>BaseMapper</code>，查看 <code>ServiceImpl</code> 的源码：</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f17c6cadd4a15ae3a9b223b1f1266d260778bff354232cfcc0c8cecf5a48fa36/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313035313930383430333234392e706e67"><img src="https://camo.githubusercontent.com/f17c6cadd4a15ae3a9b223b1f1266d260778bff354232cfcc0c8cecf5a48fa36/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313035313930383430333234392e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/2021051908403249.png" style="max-width: 100%;"></a></p>
<p dir="auto">可以看到它为我们注入了一个 <code>BaseMapper</code> 对象，而它是第一个泛型类型，也就是 <code>EmployeeMapper</code> 类型，所以我们可以直接使用这个 <code>baseMapper</code> 来调用 <code>Mapper</code> 中的方法，此时编写测试代码：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@SpringBootTest
@MapperScan(&quot;com.wwj.mybatisplusdemo.mapper&quot;)
class MybatisplusDemoApplicationTests {

    @Autowired
    private EmployeeService employeeService;

    @Test
    void contextLoads() {
        List&lt;Employee&gt; list = employeeService.listAllByLastName(&quot;tom&quot;);
        list.forEach(System.out::println);
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">SpringBootTest</span>
<span class="pl-c1">@</span><span class="pl-c1">MapperScan</span>(<span class="pl-s">"com.wwj.mybatisplusdemo.mapper"</span>)
<span class="pl-k">class</span> <span class="pl-smi">MybatisplusDemoApplicationTests</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Autowired</span>
    <span class="pl-k">private</span> <span class="pl-smi">EmployeeService</span> <span class="pl-s1">employeeService</span>;

    <span class="pl-c1">@</span><span class="pl-c1">Test</span>
    <span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
        <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">list</span> = <span class="pl-s1">employeeService</span>.<span class="pl-en">listAllByLastName</span>(<span class="pl-s">"tom"</span>);
        <span class="pl-s1">list</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
    }
}</pre></div>
<p dir="auto">运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Employee(id=2, lastName=tom, email=tom@qq.com, age=30)"><pre><span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">2</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">tom</span>, <span class="pl-s1">email</span>=<span class="pl-smi">tom</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">30</span>)</pre></div>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">ID 策略</h2><a id="user-content-id-策略" class="anchor" aria-label="Permalink: ID 策略" href="#id-策略"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">在创建表的时候我故意没有设置主键的增长策略，现在我们来插入一条数据，看看主键是如何增长的：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    Employee employee = new Employee();
    employee.setLastName(&quot;lisa&quot;);
    employee.setEmail(&quot;lisa@qq.com&quot;);
    employee.setAge(20);
    employeeService.save(employee);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">Employee</span> <span class="pl-s1">employee</span> = <span class="pl-k">new</span> <span class="pl-smi">Employee</span>();
    <span class="pl-s1">employee</span>.<span class="pl-en">setLastName</span>(<span class="pl-s">"lisa"</span>);
    <span class="pl-s1">employee</span>.<span class="pl-en">setEmail</span>(<span class="pl-s">"lisa@qq.com"</span>);
    <span class="pl-s1">employee</span>.<span class="pl-en">setAge</span>(<span class="pl-c1">20</span>);
    <span class="pl-s1">employeeService</span>.<span class="pl-en">save</span>(<span class="pl-s1">employee</span>);
}</pre></div>
<p dir="auto">插入成功后查询一下数据表：</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mysql&gt; select * from tbl_employee;
+---------------------+-----------+--------------+--------+------+
| id                  | last_name | email        | gender | age  |
+---------------------+-----------+--------------+--------+------+
|                   1 | jack      | jack@qq.com  | 1      |   35 |
|                   2 | tom       | tom@qq.com   | 1      |   30 |
|                   3 | jerry     | jerry@qq.com | 1      |   40 |
| 1385934720849584129 | lisa      | lisa@qq.com  | NULL   |   20 |
+---------------------+-----------+--------------+--------+------+
4 rows in set (0.00 sec)"><pre>mysql<span class="pl-k">&gt;</span> <span class="pl-k">select</span> <span class="pl-k">*</span> <span class="pl-k">from</span> tbl_employee;
<span class="pl-k">+</span><span class="pl-c"><span class="pl-c">--</span>-------------------+-----------+--------------+--------+------+</span>
| id                  | last_name | email        | gender | age  |
<span class="pl-k">+</span><span class="pl-c"><span class="pl-c">--</span>-------------------+-----------+--------------+--------+------+</span>
|                   <span class="pl-c1">1</span> | jack      | jack@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>  | <span class="pl-c1">1</span>      |   <span class="pl-c1">35</span> |
|                   <span class="pl-c1">2</span> | tom       | tom@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>   | <span class="pl-c1">1</span>      |   <span class="pl-c1">30</span> |
|                   <span class="pl-c1">3</span> | jerry     | jerry@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span> | <span class="pl-c1">1</span>      |   <span class="pl-c1">40</span> |
| <span class="pl-c1">1385934720849584129</span> | lisa      | lisa@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>  | <span class="pl-k">NULL</span>   |   <span class="pl-c1">20</span> |
<span class="pl-k">+</span><span class="pl-c"><span class="pl-c">--</span>-------------------+-----------+--------------+--------+------+</span>
<span class="pl-c1">4</span> rows <span class="pl-k">in</span> <span class="pl-k">set</span> (<span class="pl-c1">0</span>.<span class="pl-c1">00</span> sec)</pre></div>
<p dir="auto">可以看到 id 是一串相当长的数字，这是什么意思呢？提前剧透一下，这其实是分布式 id，那又何为分布式 id 呢？</p>
<p dir="auto">我们知道，对于一个大型应用，其访问量是非常巨大的，就比如说一个网站每天都有人进行注册，注册的用户信息就需要存入数据表，随着日子一天天过去，数据表中的用户越来越多，此时数据库的查询速度就会受到影响，所以一般情况下，当数据量足够庞大时，数据都会做分库分表的处理。</p>
<p dir="auto">然而，一旦分表，问题就产生了，很显然这些分表的数据都是属于同一张表的数据，只是因为数据量过大而分成若干张表，那么这几张表的主键 id 该怎么管理呢？每张表维护自己的 id？那数据将会有很多的 id 重复，这当然是不被允许的，其实，我们可以使用算法来生成一个绝对不会重复的 id，这样问题就迎刃而解了，事实上，分布式 id 的解决方案有很多：</p>
<ol dir="auto">
<li>UUID</li>
<li>SnowFlake</li>
<li>TinyID</li>
<li>Uidgenerator</li>
<li>Leaf</li>
<li>Tinyid</li>
<li>......</li>
</ol>
<p dir="auto">以 UUID 为例，它生成的是一串由数字和字母组成的字符串，显然并不适合作为数据表的 id，而且 id 保持递增有序会加快表的查询效率，基于此，<code>MyBatisPlus</code> 使用的就是 <code>SnowFlake</code>（雪花算法）。</p>
<p dir="auto"><code>Snowflake</code> 是 Twitter 开源的分布式 ID 生成算法。<code>Snowflake</code> 由 64 bit 的二进制数字组成，这 64bit 的二进制被分成了几部分，每一部分存储的数据都有特定的含义：</p>
<ul dir="auto">
<li><strong>第 0 位</strong>： 符号位（标识正负），始终为 0，没有用，不用管。</li>
<li><strong>第 1~41 位</strong> ：一共 41 位，用来表示时间戳，单位是毫秒，可以支撑 2 ^41 毫秒（约 69 年）</li>
<li><strong>第 42~52 位</strong> ：一共 10 位，一般来说，前 5 位表示机房 ID，后 5 位表示机器 ID（实际项目中可以根据实际情况调整）。这样就可以区分不同集群/机房的节点。</li>
<li><strong>第 53~64 位</strong> ：一共 12 位，用来表示序列号。 序列号为自增值，代表单台机器每毫秒能够产生的最大 ID 数(2^12 = 4096),也就是说单台机器每毫秒最多可以生成 4096 个 唯一 ID。</li>
</ul>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f59400d2699d8d6e0c796743ccd5e8ad9f2b748a12c67d4667505e6a425a052f/68747470733a2f2f6f7363696d672e6f736368696e612e6e65742f6f73636e65742f75702d61376535346137376235616231643966613136643561653361336335306335616565392e706e67"><img src="https://camo.githubusercontent.com/f59400d2699d8d6e0c796743ccd5e8ad9f2b748a12c67d4667505e6a425a052f/68747470733a2f2f6f7363696d672e6f736368696e612e6e65742f6f73636e65742f75702d61376535346137376235616231643966613136643561653361336335306335616565392e706e67" alt="" data-canonical-src="https://oscimg.oschina.net/oscnet/up-a7e54a77b5ab1d9fa16d5ae3a3c50c5aee9.png" style="max-width: 100%;"></a></p>
<p dir="auto">这也就是为什么插入数据后新的数据 id 是一长串数字的原因了，我们可以在实体类中使用 <code>@TableId</code> 来设置主键的策略：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
@TableName(&quot;tbl_employee&quot;)
public class Employee {

    @TableId(type = IdType.AUTO) // 设置主键策略
    private Long id;
    private String lastName;
    private String email;
    private Integer age;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-c1">@</span><span class="pl-c1">TableName</span>(<span class="pl-s">"tbl_employee"</span>)
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Employee</span> {

    <span class="pl-c1">@</span><span class="pl-c1">TableId</span>(<span class="pl-s1">type</span> = <span class="pl-smi">IdType</span>.<span class="pl-c1">AUTO</span>) <span class="pl-c">// 设置主键策略</span>
    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">email</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">age</span>;
}</pre></div>
<p dir="auto"><code>MyBatisPlus</code> 提供了几种主键的策略：
<a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/15859143f5966f7cb467c2cdadca0335437c1d8bcc4d9f8250544b170f799e3e/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343031313734352e706e67"><img src="https://camo.githubusercontent.com/15859143f5966f7cb467c2cdadca0335437c1d8bcc4d9f8250544b170f799e3e/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038343031313734352e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210519084011745.png" style="max-width: 100%;"></a>
其中 <code>AUTO</code> 表示数据库自增策略，该策略下需要数据库实现主键的自增（auto_increment)，<code>ASSIGN_ID</code> 是雪花算法，默认使用的是该策略，<code>ASSIGN_UUID</code> 是 UUID 策略，一般不会使用该策略。</p>
<p dir="auto">这里多说一点， 当实体类的主键名为 id，并且数据表的主键名也为 id 时，此时 <code>MyBatisPlus</code> 会自动判定该属性为主键 id，倘若名字不是 id 时，就需要标注 <code>@TableId</code> 注解，若是实体类中主键名与数据表的主键名不一致，则可以进行声明：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@TableId(value = &quot;uid&quot;,type = IdType.AUTO) // 设置主键策略
private Long id;"><pre><span class="pl-c1">@</span><span class="pl-c1">TableId</span>(<span class="pl-s1">value</span> = <span class="pl-s">"uid"</span>,<span class="pl-s1">type</span> = <span class="pl-smi">IdType</span>.<span class="pl-c1">AUTO</span>) <span class="pl-c">// 设置主键策略</span>
<span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;</pre></div>
<p dir="auto">还可以在配置文件中配置全局的主键策略：</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mybatis-plus:
  global-config:
    db-config:
      id-type: auto"><pre><span class="pl-ent">mybatis-plus</span>:
  <span class="pl-ent">global-config</span>:
    <span class="pl-ent">db-config</span>:
      <span class="pl-ent">id-type</span>: <span class="pl-s">auto</span></pre></div>
<p dir="auto">这样能够避免在每个实体类中重复设置主键策略。</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">属性自动填充</h2><a id="user-content-属性自动填充" class="anchor" aria-label="Permalink: 属性自动填充" href="#属性自动填充"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">翻阅《阿里巴巴Java开发手册》，在第 5 章 MySQL 数据库可以看到这样一条规范：
<a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f5d2c2562996645cce44f85469c2644830592819ffa292bdc80ac8d1a837ea02/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231343832313338392e706e67"><img src="https://camo.githubusercontent.com/f5d2c2562996645cce44f85469c2644830592819ffa292bdc80ac8d1a837ea02/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231343832313338392e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210426214821389.png" style="max-width: 100%;"></a>
对于一张数据表，它必须具备三个字段：</p>
<ul dir="auto">
<li><code>id</code> : 唯一ID</li>
<li><code>gmt_create</code> : 保存的是当前数据创建的时间</li>
<li><code>gmt_modified</code> : 保存的是更新时间</li>
</ul>
<p dir="auto">我们改造一下数据表：</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="alter table tbl_employee add column gmt_create datetime not null;
alter table tbl_employee add column gmt_modified datetime not null;"><pre><span class="pl-k">alter</span> <span class="pl-k">table</span> tbl_employee add column gmt_create datetime <span class="pl-k">not null</span>;
<span class="pl-k">alter</span> <span class="pl-k">table</span> tbl_employee add column gmt_modified datetime <span class="pl-k">not null</span>;</pre></div>
<p dir="auto">然后改造一下实体类：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
@TableName(&quot;tbl_employee&quot;)
public class Employee {

    @TableId(type = IdType.AUTO) // 设置主键策略
    private Long id;
    private String lastName;
    private String email;
    private Integer age;
    private LocalDateTime gmtCreate;
    private LocalDateTime gmtModified;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-c1">@</span><span class="pl-c1">TableName</span>(<span class="pl-s">"tbl_employee"</span>)
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Employee</span> {

    <span class="pl-c1">@</span><span class="pl-c1">TableId</span>(<span class="pl-s1">type</span> = <span class="pl-smi">IdType</span>.<span class="pl-c1">AUTO</span>) <span class="pl-c">// 设置主键策略</span>
    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">email</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">age</span>;
    <span class="pl-k">private</span> <span class="pl-smi">LocalDateTime</span> <span class="pl-s1">gmtCreate</span>;
    <span class="pl-k">private</span> <span class="pl-smi">LocalDateTime</span> <span class="pl-s1">gmtModified</span>;
}</pre></div>
<p dir="auto">此时我们在插入数据和更新数据的时候就需要手动去维护这两个属性：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    Employee employee = new Employee();
    employee.setLastName(&quot;lisa&quot;);
    employee.setEmail(&quot;lisa@qq.com&quot;);
    employee.setAge(20);
    // 设置创建时间
    employee.setGmtCreate(LocalDateTime.now());
    employee.setGmtModified(LocalDateTime.now());
    employeeService.save(employee);
}

@Test
void contextLoads() {
    Employee employee = new Employee();
    employee.setId(1385934720849584130L);
    employee.setAge(50);
    // 设置创建时间
    employee.setGmtModified(LocalDateTime.now());
    employeeService.updateById(employee);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">Employee</span> <span class="pl-s1">employee</span> = <span class="pl-k">new</span> <span class="pl-smi">Employee</span>();
    <span class="pl-s1">employee</span>.<span class="pl-en">setLastName</span>(<span class="pl-s">"lisa"</span>);
    <span class="pl-s1">employee</span>.<span class="pl-en">setEmail</span>(<span class="pl-s">"lisa@qq.com"</span>);
    <span class="pl-s1">employee</span>.<span class="pl-en">setAge</span>(<span class="pl-c1">20</span>);
    <span class="pl-c">// 设置创建时间</span>
    <span class="pl-s1">employee</span>.<span class="pl-en">setGmtCreate</span>(<span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
    <span class="pl-s1">employee</span>.<span class="pl-en">setGmtModified</span>(<span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
    <span class="pl-s1">employeeService</span>.<span class="pl-en">save</span>(<span class="pl-s1">employee</span>);
}

<span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">Employee</span> <span class="pl-s1">employee</span> = <span class="pl-k">new</span> <span class="pl-smi">Employee</span>();
    <span class="pl-s1">employee</span>.<span class="pl-en">setId</span>(<span class="pl-c1">1385934720849584130L</span>);
    <span class="pl-s1">employee</span>.<span class="pl-en">setAge</span>(<span class="pl-c1">50</span>);
    <span class="pl-c">// 设置创建时间</span>
    <span class="pl-s1">employee</span>.<span class="pl-en">setGmtModified</span>(<span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
    <span class="pl-s1">employeeService</span>.<span class="pl-en">updateById</span>(<span class="pl-s1">employee</span>);
}</pre></div>
<p dir="auto">每次都需要维护这两个属性未免过于麻烦，好在 <code>MyBatisPlus</code> 提供了字段自动填充功能来帮助我们进行管理，需要使用到的是 <code>@TableField</code> 注解：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
@TableName(&quot;tbl_employee&quot;)
public class Employee {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String lastName;
    private String email;
    private Integer age;
    @TableField(fill = FieldFill.INSERT) // 插入的时候自动填充
    private LocalDateTime gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新的时候自动填充
    private LocalDateTime gmtModified;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-c1">@</span><span class="pl-c1">TableName</span>(<span class="pl-s">"tbl_employee"</span>)
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Employee</span> {

    <span class="pl-c1">@</span><span class="pl-c1">TableId</span>(<span class="pl-s1">type</span> = <span class="pl-smi">IdType</span>.<span class="pl-c1">AUTO</span>)
    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">email</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">age</span>;
    <span class="pl-c1">@</span><span class="pl-c1">TableField</span>(<span class="pl-s1">fill</span> = <span class="pl-smi">FieldFill</span>.<span class="pl-c1">INSERT</span>) <span class="pl-c">// 插入的时候自动填充</span>
    <span class="pl-k">private</span> <span class="pl-smi">LocalDateTime</span> <span class="pl-s1">gmtCreate</span>;
    <span class="pl-c1">@</span><span class="pl-c1">TableField</span>(<span class="pl-s1">fill</span> = <span class="pl-smi">FieldFill</span>.<span class="pl-c1">INSERT_UPDATE</span>) <span class="pl-c">// 插入和更新的时候自动填充</span>
    <span class="pl-k">private</span> <span class="pl-smi">LocalDateTime</span> <span class="pl-s1">gmtModified</span>;
}</pre></div>
<p dir="auto">然后编写一个类实现 MetaObjectHandler 接口：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 实现插入时的自动填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info(&quot;insert开始属性填充&quot;);
        this.strictInsertFill(metaObject,&quot;gmtCreate&quot;, LocalDateTime.class,LocalDateTime.now());
        this.strictInsertFill(metaObject,&quot;gmtModified&quot;, LocalDateTime.class,LocalDateTime.now());
    }

    /**
     * 实现更新时的自动填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info(&quot;update开始属性填充&quot;);
        this.strictInsertFill(metaObject,&quot;gmtModified&quot;, LocalDateTime.class,LocalDateTime.now());
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Component</span>
<span class="pl-c1">@</span><span class="pl-c1">Slf4j</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">MyMetaObjectHandler</span> <span class="pl-k">implements</span> <span class="pl-smi">MetaObjectHandler</span> {

    <span class="pl-c">/**</span>
<span class="pl-c">     * 实现插入时的自动填充</span>
<span class="pl-c">     * @param metaObject</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">@</span><span class="pl-c1">Override</span>
    <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">insertFill</span>(<span class="pl-smi">MetaObject</span> <span class="pl-s1">metaObject</span>) {
        <span class="pl-s1">log</span>.<span class="pl-en">info</span>(<span class="pl-s">"insert开始属性填充"</span>);
        <span class="pl-smi">this</span>.<span class="pl-en">strictInsertFill</span>(<span class="pl-s1">metaObject</span>,<span class="pl-s">"gmtCreate"</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-k">class</span>,<span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
        <span class="pl-smi">this</span>.<span class="pl-en">strictInsertFill</span>(<span class="pl-s1">metaObject</span>,<span class="pl-s">"gmtModified"</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-k">class</span>,<span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
    }

    <span class="pl-c">/**</span>
<span class="pl-c">     * 实现更新时的自动填充</span>
<span class="pl-c">     * @param metaObject</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">@</span><span class="pl-c1">Override</span>
    <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">updateFill</span>(<span class="pl-smi">MetaObject</span> <span class="pl-s1">metaObject</span>) {
        <span class="pl-s1">log</span>.<span class="pl-en">info</span>(<span class="pl-s">"update开始属性填充"</span>);
        <span class="pl-smi">this</span>.<span class="pl-en">strictInsertFill</span>(<span class="pl-s1">metaObject</span>,<span class="pl-s">"gmtModified"</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-k">class</span>,<span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
    }
}</pre></div>
<p dir="auto">该接口中有两个未实现的方法，分别为插入和更新时的填充方法，在方法中调用 <code>strictInsertFill()</code> 方法 即可实现属性的填充，它需要四个参数：</p>
<ol dir="auto">
<li><code>metaObject</code>：元对象，就是方法的入参</li>
<li><code>fieldName</code>：为哪个属性进行自动填充</li>
<li><code>fieldType</code>：属性的类型</li>
<li><code>fieldVal</code>：需要填充的属性值</li>
</ol>
<p dir="auto">此时在插入和更新数据之前，这两个方法会先被执行，以实现属性的自动填充，通过日志我们可以进行验证：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    Employee employee = new Employee();
    employee.setId(1385934720849584130L);
    employee.setAge(15);
    employeeService.updateById(employee);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">Employee</span> <span class="pl-s1">employee</span> = <span class="pl-k">new</span> <span class="pl-smi">Employee</span>();
    <span class="pl-s1">employee</span>.<span class="pl-en">setId</span>(<span class="pl-c1">1385934720849584130L</span>);
    <span class="pl-s1">employee</span>.<span class="pl-en">setAge</span>(<span class="pl-c1">15</span>);
    <span class="pl-s1">employeeService</span>.<span class="pl-en">updateById</span>(<span class="pl-s1">employee</span>);
}</pre></div>
<p dir="auto">运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="INFO 15584 --- [           main] c.w.m.handler.MyMetaObjectHandler        : update开始属性填充
2021-04-24 21:32:19.788  INFO 15584 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-04-24 21:32:21.244  INFO 15584 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed."><pre><span class="pl-c1">INFO</span> <span class="pl-c1">15584</span> ---<span class="pl-s1"></span> [           <span class="pl-s1">main</span>] <span class="pl-s1">c</span>.<span class="pl-s1">w</span>.<span class="pl-s1">m</span>.<span class="pl-s1">handler</span>.<span class="pl-s1">MyMetaObjectHandler</span>        : <span class="pl-s1">update开始属性填充</span>
<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">32</span>:<span class="pl-c1">19.788</span>  <span class="pl-c1">INFO</span> <span class="pl-c1">15584</span> ---<span class="pl-s1"></span> [           <span class="pl-s1">main</span>] <span class="pl-s1">com</span>.<span class="pl-s1">zaxxer</span>.<span class="pl-s1">hikari</span>.<span class="pl-s1">HikariDataSource</span>       : <span class="pl-s1">HikariPool</span>-<span class="pl-c1">1</span> - <span class="pl-s1">Starting</span>...
<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">32</span>:<span class="pl-c1">21.244</span>  <span class="pl-c1">INFO</span> <span class="pl-c1">15584</span> ---<span class="pl-s1"></span> [           <span class="pl-s1">main</span>] <span class="pl-s1">com</span>.<span class="pl-s1">zaxxer</span>.<span class="pl-s1">hikari</span>.<span class="pl-s1">HikariDataSource</span>       : <span class="pl-s1">HikariPool</span>-<span class="pl-c1">1</span> - <span class="pl-smi">Start</span> <span class="pl-s1">completed</span>.</pre></div>
<p dir="auto">属性填充其实可以进行一些优化，考虑一些特殊情况，对于一些不存在的属性，就不需要进行属性填充，对于一些设置了值的属性，也不需要进行属性填充，这样可以提高程序的整体运行效率：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        boolean hasGmtCreate = metaObject.hasSetter(&quot;gmtCreate&quot;);
        boolean hasGmtModified = metaObject.hasSetter(&quot;gmtModified&quot;);
        if (hasGmtCreate) {
            Object gmtCreate = this.getFieldValByName(&quot;gmtCreate&quot;, metaObject);
            if (gmtCreate == null) {
                this.strictInsertFill(metaObject, &quot;gmtCreate&quot;, LocalDateTime.class, LocalDateTime.now());
            }
        }
        if (hasGmtModified) {
            Object gmtModified = this.getFieldValByName(&quot;gmtModified&quot;, metaObject);
            if (gmtModified == null) {
                this.strictInsertFill(metaObject, &quot;gmtModified&quot;, LocalDateTime.class, LocalDateTime.now());
            }
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        boolean hasGmtModified = metaObject.hasSetter(&quot;gmtModified&quot;);
        if (hasGmtModified) {
            Object gmtModified = this.getFieldValByName(&quot;gmtModified&quot;, metaObject);
            if (gmtModified == null) {
                this.strictInsertFill(metaObject, &quot;gmtModified&quot;, LocalDateTime.class, LocalDateTime.now());
            }
        }
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Component</span>
<span class="pl-c1">@</span><span class="pl-c1">Slf4j</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">MyMetaObjectHandler</span> <span class="pl-k">implements</span> <span class="pl-smi">MetaObjectHandler</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Override</span>
    <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">insertFill</span>(<span class="pl-smi">MetaObject</span> <span class="pl-s1">metaObject</span>) {
        <span class="pl-smi">boolean</span> <span class="pl-s1">hasGmtCreate</span> = <span class="pl-s1">metaObject</span>.<span class="pl-en">hasSetter</span>(<span class="pl-s">"gmtCreate"</span>);
        <span class="pl-smi">boolean</span> <span class="pl-s1">hasGmtModified</span> = <span class="pl-s1">metaObject</span>.<span class="pl-en">hasSetter</span>(<span class="pl-s">"gmtModified"</span>);
        <span class="pl-k">if</span> (<span class="pl-s1">hasGmtCreate</span>) {
            <span class="pl-smi">Object</span> <span class="pl-s1">gmtCreate</span> = <span class="pl-smi">this</span>.<span class="pl-en">getFieldValByName</span>(<span class="pl-s">"gmtCreate"</span>, <span class="pl-s1">metaObject</span>);
            <span class="pl-k">if</span> (<span class="pl-s1">gmtCreate</span> == <span class="pl-c1">null</span>) {
                <span class="pl-smi">this</span>.<span class="pl-en">strictInsertFill</span>(<span class="pl-s1">metaObject</span>, <span class="pl-s">"gmtCreate"</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-k">class</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
            }
        }
        <span class="pl-k">if</span> (<span class="pl-s1">hasGmtModified</span>) {
            <span class="pl-smi">Object</span> <span class="pl-s1">gmtModified</span> = <span class="pl-smi">this</span>.<span class="pl-en">getFieldValByName</span>(<span class="pl-s">"gmtModified"</span>, <span class="pl-s1">metaObject</span>);
            <span class="pl-k">if</span> (<span class="pl-s1">gmtModified</span> == <span class="pl-c1">null</span>) {
                <span class="pl-smi">this</span>.<span class="pl-en">strictInsertFill</span>(<span class="pl-s1">metaObject</span>, <span class="pl-s">"gmtModified"</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-k">class</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
            }
        }
    }

    <span class="pl-c1">@</span><span class="pl-c1">Override</span>
    <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">updateFill</span>(<span class="pl-smi">MetaObject</span> <span class="pl-s1">metaObject</span>) {
        <span class="pl-smi">boolean</span> <span class="pl-s1">hasGmtModified</span> = <span class="pl-s1">metaObject</span>.<span class="pl-en">hasSetter</span>(<span class="pl-s">"gmtModified"</span>);
        <span class="pl-k">if</span> (<span class="pl-s1">hasGmtModified</span>) {
            <span class="pl-smi">Object</span> <span class="pl-s1">gmtModified</span> = <span class="pl-smi">this</span>.<span class="pl-en">getFieldValByName</span>(<span class="pl-s">"gmtModified"</span>, <span class="pl-s1">metaObject</span>);
            <span class="pl-k">if</span> (<span class="pl-s1">gmtModified</span> == <span class="pl-c1">null</span>) {
                <span class="pl-smi">this</span>.<span class="pl-en">strictInsertFill</span>(<span class="pl-s1">metaObject</span>, <span class="pl-s">"gmtModified"</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-k">class</span>, <span class="pl-smi">LocalDateTime</span>.<span class="pl-en">now</span>());
            }
        }
    }
}</pre></div>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">逻辑删除</h2><a id="user-content-逻辑删除" class="anchor" aria-label="Permalink: 逻辑删除" href="#逻辑删除"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">逻辑删除对应的是物理删除，分别介绍一下这两个概念：</p>
<ol dir="auto">
<li><strong>物理删除</strong> ：指的是真正的删除，即：当执行删除操作时，将数据表中的数据进行删除，之后将无法再查询到该数据</li>
<li><strong>逻辑删除</strong> ：并不是真正意义上的删除，只是对于用户不可见了，它仍然存在与数据表中</li>
</ol>
<p dir="auto">在这个数据为王的时代，数据就是财富，所以一般并不会有哪个系统在删除某些重要数据时真正删掉了数据，通常都是在数据库中建立一个状态列，让其默认为 0，当为 0 时，用户可见；当执行了删除操作，就将状态列改为 1，此时用户不可见，但数据还是在表中的。</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1a6f590c2b990911ba84c0ef9038887a454e831c17a607e496e2bb355ec3b46f/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231353130373231302e706e67"><img src="https://camo.githubusercontent.com/1a6f590c2b990911ba84c0ef9038887a454e831c17a607e496e2bb355ec3b46f/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363231353130373231302e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210426215107210.png" style="max-width: 100%;"></a></p>
<p dir="auto">按照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议，我们来为数据表新增一个<code>is_deleted</code> 字段：</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="alter table tbl_employee add column is_deleted tinyint not null;"><pre><span class="pl-k">alter</span> <span class="pl-k">table</span> tbl_employee add column is_deleted tinyint <span class="pl-k">not null</span>;</pre></div>
<p dir="auto">在实体类中也要添加这一属性：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
@TableName(&quot;tbl_employee&quot;)
public class Employee {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String lastName;
    private String email;
    private Integer age;
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime gmtModified;
    /**
     * 逻辑删除属性
     */
    @TableLogic
    @TableField(&quot;is_deleted&quot;)
    private Boolean deleted;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-c1">@</span><span class="pl-c1">TableName</span>(<span class="pl-s">"tbl_employee"</span>)
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Employee</span> {

    <span class="pl-c1">@</span><span class="pl-c1">TableId</span>(<span class="pl-s1">type</span> = <span class="pl-smi">IdType</span>.<span class="pl-c1">AUTO</span>)
    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">lastName</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">email</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">age</span>;
    <span class="pl-c1">@</span><span class="pl-c1">TableField</span>(<span class="pl-s1">fill</span> = <span class="pl-smi">FieldFill</span>.<span class="pl-c1">INSERT</span>)
    <span class="pl-k">private</span> <span class="pl-smi">LocalDateTime</span> <span class="pl-s1">gmtCreate</span>;
    <span class="pl-c1">@</span><span class="pl-c1">TableField</span>(<span class="pl-s1">fill</span> = <span class="pl-smi">FieldFill</span>.<span class="pl-c1">INSERT_UPDATE</span>)
    <span class="pl-k">private</span> <span class="pl-smi">LocalDateTime</span> <span class="pl-s1">gmtModified</span>;
    <span class="pl-c">/**</span>
<span class="pl-c">     * 逻辑删除属性</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">@</span><span class="pl-c1">TableLogic</span>
    <span class="pl-c1">@</span><span class="pl-c1">TableField</span>(<span class="pl-s">"is_deleted"</span>)
    <span class="pl-k">private</span> <span class="pl-smi">Boolean</span> <span class="pl-s1">deleted</span>;
}</pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/243c18c226a2e34b57bcca15fcfc1984321776c156ae36338aac4fa77cc91030/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313034323632313533303136322e706e67"><img src="https://camo.githubusercontent.com/243c18c226a2e34b57bcca15fcfc1984321776c156ae36338aac4fa77cc91030/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f323032313034323632313533303136322e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/2021042621530162.png" style="max-width: 100%;"></a></p>
<p dir="auto">还是参照《阿里巴巴Java开发手册》第 5 章 MySQL 数据库相关的建议，对于布尔类型变量，不能加 is 前缀，所以我们的属性被命名为 <code>deleted</code>，但此时就无法与数据表的字段进行对应了，所以我们需要使用 <code>@TableField</code> 注解来声明一下数据表的字段名，而 <code>@TableLogin</code> 注解用于设置逻辑删除属性；此时我们执行删除操作：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    employeeService.removeById(3);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-s1">employeeService</span>.<span class="pl-en">removeById</span>(<span class="pl-c1">3</span>);
}</pre></div>
<p dir="auto">查询数据表：</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mysql&gt; select * from tbl_employee;
+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+
| id                  | last_name | email        | gender | age  | gmt_create          | gmt_modified        | is_deleted |
+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+
|                   1 | jack      | jack@qq.com  | 1      |   35 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |
|                   2 | tom       | tom@qq.com   | 1      |   30 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |
|                   3 | jerry     | jerry@qq.com | 1      |   40 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          1 |
| 1385934720849584129 | lisa      | lisa@qq.com  | NULL   |   20 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |          0 |
| 1385934720849584130 | lisa      | lisa@qq.com  | NULL   |   15 | 2021-04-24 21:14:18 | 2021-04-24 21:32:19 |          0 |
+---------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+
5 rows in set (0.00 sec)"><pre>mysql<span class="pl-k">&gt;</span> <span class="pl-k">select</span> <span class="pl-k">*</span> <span class="pl-k">from</span> tbl_employee;
<span class="pl-k">+</span><span class="pl-c"><span class="pl-c">--</span>-------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+</span>
| id                  | last_name | email        | gender | age  | gmt_create          | gmt_modified        | is_deleted |
<span class="pl-k">+</span><span class="pl-c"><span class="pl-c">--</span>-------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+</span>
|                   <span class="pl-c1">1</span> | jack      | jack@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>  | <span class="pl-c1">1</span>      |   <span class="pl-c1">35</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> |          <span class="pl-c1">0</span> |
|                   <span class="pl-c1">2</span> | tom       | tom@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>   | <span class="pl-c1">1</span>      |   <span class="pl-c1">30</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> |          <span class="pl-c1">0</span> |
|                   <span class="pl-c1">3</span> | jerry     | jerry@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span> | <span class="pl-c1">1</span>      |   <span class="pl-c1">40</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> |          <span class="pl-c1">1</span> |
| <span class="pl-c1">1385934720849584129</span> | lisa      | lisa@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>  | <span class="pl-k">NULL</span>   |   <span class="pl-c1">20</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> | <span class="pl-c1">0000</span><span class="pl-k">-</span><span class="pl-c1">00</span><span class="pl-k">-</span><span class="pl-c1">00</span> <span class="pl-c1">00</span>:<span class="pl-c1">00</span>:<span class="pl-c1">00</span> |          <span class="pl-c1">0</span> |
| <span class="pl-c1">1385934720849584130</span> | lisa      | lisa@<span class="pl-c1">qq</span>.<span class="pl-c1">com</span>  | <span class="pl-k">NULL</span>   |   <span class="pl-c1">15</span> | <span class="pl-c1">2021</span><span class="pl-k">-</span><span class="pl-c1">04</span><span class="pl-k">-</span><span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span> | <span class="pl-c1">2021</span><span class="pl-k">-</span><span class="pl-c1">04</span><span class="pl-k">-</span><span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">32</span>:<span class="pl-c1">19</span> |          <span class="pl-c1">0</span> |
<span class="pl-k">+</span><span class="pl-c"><span class="pl-c">--</span>-------------------+-----------+--------------+--------+------+---------------------+---------------------+------------+</span>
<span class="pl-c1">5</span> rows <span class="pl-k">in</span> <span class="pl-k">set</span> (<span class="pl-c1">0</span>.<span class="pl-c1">00</span> sec)</pre></div>
<p dir="auto">可以看到数据并没有被删除，只是 <code>is_deleted</code> 字段的属性值被更新成了 1，此时我们再来执行查询操作：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    List&lt;Employee&gt; list = employeeService.list();
    list.forEach(System.out::println);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">list</span> = <span class="pl-s1">employeeService</span>.<span class="pl-en">list</span>();
    <span class="pl-s1">list</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
}</pre></div>
<p dir="auto">执行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)
Employee(id=2, lastName=tom, email=tom@qq.com, age=30, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)
Employee(id=1385934720849584129, lastName=lisa, email=lisa@qq.com, age=20, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=false)
Employee(id=1385934720849584130, lastName=lisa, email=lisa@qq.com, age=15, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:32:19, deleted=false)"><pre><span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jack</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jack</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">35</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">false</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">2</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">tom</span>, <span class="pl-s1">email</span>=<span class="pl-smi">tom</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">30</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">false</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1385934720849584129</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">lisa</span>, <span class="pl-s1">email</span>=<span class="pl-smi">lisa</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">20</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">false</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1385934720849584130</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">lisa</span>, <span class="pl-s1">email</span>=<span class="pl-smi">lisa</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">15</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">32</span>:<span class="pl-c1">19</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">false</span>)</pre></div>
<p dir="auto">会发现第三条数据并没有被查询出来，它是如何实现的呢？我们可以输出 <code>MyBatisPlus</code> 生成的 SQL 来分析一下，在配置文件中进行配置：</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出SQL日志"><pre><span class="pl-ent">mybatis-plus</span>:
  <span class="pl-ent">configuration</span>:
    <span class="pl-ent">log-impl</span>: <span class="pl-s">org.apache.ibatis.logging.stdout.StdOutImpl </span><span class="pl-c"><span class="pl-c">#</span> 输出SQL日志</span></pre></div>
<p dir="auto">运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="==&gt;  Preparing: SELECT id,last_name,email,age,gmt_create,gmt_modified,is_deleted AS deleted FROM tbl_employee WHERE is_deleted=0
==&gt; Parameters:
&lt;==    Columns: id, last_name, email, age, gmt_create, gmt_modified, deleted
&lt;==        Row: 1, jack, jack@qq.com, 35, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0
&lt;==        Row: 2, tom, tom@qq.com, 30, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0
&lt;==        Row: 1385934720849584129, lisa, lisa@qq.com, 20, 2021-04-24 21:14:18, 2021-04-24 21:14:18, 0
&lt;==        Row: 1385934720849584130, lisa, lisa@qq.com, 15, 2021-04-24 21:14:18, 2021-04-24 21:32:19, 0
&lt;==      Total: 4"><pre>==&gt;  <span class="pl-s1">Preparing</span>: <span class="pl-smi">SELECT</span> <span class="pl-s1">id</span>,<span class="pl-s1">last_name</span>,<span class="pl-s1">email</span>,<span class="pl-s1">age</span>,<span class="pl-s1">gmt_create</span>,<span class="pl-s1">gmt_modified</span>,<span class="pl-s1">is_deleted</span> <span class="pl-smi">AS</span> <span class="pl-s1">deleted</span> <span class="pl-smi">FROM</span> <span class="pl-s1">tbl_employee</span> <span class="pl-smi">WHERE</span> <span class="pl-s1">is_deleted</span>=<span class="pl-c1">0</span>
==&gt; <span class="pl-s1">Parameters</span>:
&lt;==    <span class="pl-s1">Columns</span>: <span class="pl-s1">id</span>, <span class="pl-s1">last_name</span>, <span class="pl-s1">email</span>, <span class="pl-s1">age</span>, <span class="pl-s1">gmt_create</span>, <span class="pl-s1">gmt_modified</span>, <span class="pl-s1">deleted</span>
&lt;==        <span class="pl-s1">Row</span>: <span class="pl-c1">1</span>, <span class="pl-s1">jack</span>, <span class="pl-s1">jack</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-c1">35</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">0</span>
&lt;==        <span class="pl-s1">Row</span>: <span class="pl-c1">2</span>, <span class="pl-s1">tom</span>, <span class="pl-s1">tom</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-c1">30</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">0</span>
&lt;==        <span class="pl-s1">Row</span>: <span class="pl-c1">1385934720849584129</span>, <span class="pl-s1">lisa</span>, <span class="pl-s1">lisa</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-c1">20</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">0</span>
&lt;==        <span class="pl-s1">Row</span>: <span class="pl-c1">1385934720849584130</span>, <span class="pl-s1">lisa</span>, <span class="pl-s1">lisa</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-c1">15</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span> <span class="pl-c1">21</span>:<span class="pl-c1">32</span>:<span class="pl-c1">19</span>, <span class="pl-c1">0</span>
&lt;==      <span class="pl-s1">Total</span>: <span class="pl-c1">4</span></pre></div>
<p dir="auto">原来它在查询时携带了一个条件： <code>is_deleted=0</code> ，这也说明了 <code>MyBatisPlus</code> 默认 0 为不删除，1 为删除。
若是你想修改这个规定，比如设置-1 为删除，1 为不删除，也可以进行配置：</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      logic-delete-field: deleted # 逻辑删除属性名
      logic-delete-value: -1 # 删除值
      logic-not-delete-value: 1 # 不删除值"><pre><span class="pl-ent">mybatis-plus</span>:
  <span class="pl-ent">global-config</span>:
    <span class="pl-ent">db-config</span>:
      <span class="pl-ent">id-type</span>: <span class="pl-s">auto</span>
      <span class="pl-ent">logic-delete-field</span>: <span class="pl-s">deleted </span><span class="pl-c"><span class="pl-c">#</span> 逻辑删除属性名</span>
      <span class="pl-ent">logic-delete-value</span>: <span class="pl-c1">-1</span> <span class="pl-c"><span class="pl-c">#</span> 删除值</span>
      <span class="pl-ent">logic-not-delete-value</span>: <span class="pl-c1">1</span> <span class="pl-c"><span class="pl-c">#</span> 不删除值</span></pre></div>
<p dir="auto">但建议使用默认的配置，阿里巴巴开发手册也规定 1 表示删除，0 表示未删除。</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">分页插件</h2><a id="user-content-分页插件" class="anchor" aria-label="Permalink: 分页插件" href="#分页插件"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">对于分页功能，<code>MyBatisPlus</code> 提供了分页插件，只需要进行简单的配置即可实现：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Configuration
public class MyBatisConfig {

    /**
     * 注册分页插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Configuration</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">MyBatisConfig</span> {

    <span class="pl-c">/**</span>
<span class="pl-c">     * 注册分页插件</span>
<span class="pl-c">     * @return</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">@</span><span class="pl-c1">Bean</span>
    <span class="pl-k">public</span> <span class="pl-smi">MybatisPlusInterceptor</span> <span class="pl-en">mybatisPlusInterceptor</span>() {
        <span class="pl-smi">MybatisPlusInterceptor</span> <span class="pl-s1">interceptor</span> = <span class="pl-k">new</span> <span class="pl-smi">MybatisPlusInterceptor</span>();
        <span class="pl-s1">interceptor</span>.<span class="pl-en">addInnerInterceptor</span>(<span class="pl-k">new</span> <span class="pl-smi">PaginationInnerInterceptor</span>(<span class="pl-smi">DbType</span>.<span class="pl-c1">MYSQL</span>));
        <span class="pl-k">return</span> <span class="pl-s1">interceptor</span>;
    }
}</pre></div>
<p dir="auto">接下来我们就可以使用分页插件提供的功能了：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    Page&lt;Employee&gt; page = new Page&lt;&gt;(1,2);
    employeeService.page(page, null);
    List&lt;Employee&gt; employeeList = page.getRecords();
    employeeList.forEach(System.out::println);
    System.out.println(&quot;获取总条数:&quot; + page.getTotal());
    System.out.println(&quot;获取当前页码:&quot; + page.getCurrent());
    System.out.println(&quot;获取总页码:&quot; + page.getPages());
    System.out.println(&quot;获取每页显示的数据条数:&quot; + page.getSize());
    System.out.println(&quot;是否有上一页:&quot; + page.hasPrevious());
    System.out.println(&quot;是否有下一页:&quot; + page.hasNext());
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">Page</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">page</span> = <span class="pl-k">new</span> <span class="pl-smi">Page</span>&lt;&gt;(<span class="pl-c1">1</span>,<span class="pl-c1">2</span>);
    <span class="pl-s1">employeeService</span>.<span class="pl-en">page</span>(<span class="pl-s1">page</span>, <span class="pl-c1">null</span>);
    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">employeeList</span> = <span class="pl-s1">page</span>.<span class="pl-en">getRecords</span>();
    <span class="pl-s1">employeeList</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"获取总条数:"</span> + <span class="pl-s1">page</span>.<span class="pl-en">getTotal</span>());
    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"获取当前页码:"</span> + <span class="pl-s1">page</span>.<span class="pl-en">getCurrent</span>());
    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"获取总页码:"</span> + <span class="pl-s1">page</span>.<span class="pl-en">getPages</span>());
    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"获取每页显示的数据条数:"</span> + <span class="pl-s1">page</span>.<span class="pl-en">getSize</span>());
    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"是否有上一页:"</span> + <span class="pl-s1">page</span>.<span class="pl-en">hasPrevious</span>());
    <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"是否有下一页:"</span> + <span class="pl-s1">page</span>.<span class="pl-en">hasNext</span>());
}</pre></div>
<p dir="auto">其中的 <code>Page</code> 对象用于指定分页查询的规则，这里表示按每页两条数据进行分页，并查询第一页的内容，运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)
Employee(id=2, lastName=tom, email=tom@qq.com, age=30, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)
获取总条数:4
获取当前页码:1
获取总页码:2
获取每页显示的数据条数:2
是否有上一页:false
是否有下一页:true"><pre><span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jack</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jack</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">35</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">0</span>)
<span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">2</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">tom</span>, <span class="pl-s1">email</span>=<span class="pl-smi">tom</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">30</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">0</span>)
<span class="pl-s1">获取总条数</span>:<span class="pl-c1">4</span>
<span class="pl-s1">获取当前页码</span>:<span class="pl-c1">1</span>
<span class="pl-s1">获取总页码</span>:<span class="pl-c1">2</span>
<span class="pl-s1">获取每页显示的数据条数</span>:<span class="pl-c1">2</span>
<span class="pl-s1">是否有上一页</span>:<span class="pl-c1">false</span>
<span class="pl-s1">是否有下一页</span>:<span class="pl-c1">true</span></pre></div>
<p dir="auto">倘若在分页过程中需要限定一些条件，我们就需要构建 QueryWrapper 来实现：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    Page&lt;Employee&gt; page = new Page&lt;&gt;(1, 2);
    employeeService.page(page, new QueryWrapper&lt;Employee&gt;()
                         .between(&quot;age&quot;, 20, 50)
                         .eq(&quot;gender&quot;, 1));
    List&lt;Employee&gt; employeeList = page.getRecords();
    employeeList.forEach(System.out::println);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">Page</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">page</span> = <span class="pl-k">new</span> <span class="pl-smi">Page</span>&lt;&gt;(<span class="pl-c1">1</span>, <span class="pl-c1">2</span>);
    <span class="pl-s1">employeeService</span>.<span class="pl-en">page</span>(<span class="pl-s1">page</span>, <span class="pl-k">new</span> <span class="pl-smi">QueryWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt;()
                         .<span class="pl-en">between</span>(<span class="pl-s">"age"</span>, <span class="pl-c1">20</span>, <span class="pl-c1">50</span>)
                         .<span class="pl-en">eq</span>(<span class="pl-s">"gender"</span>, <span class="pl-c1">1</span>));
    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">employeeList</span> = <span class="pl-s1">page</span>.<span class="pl-en">getRecords</span>();
    <span class="pl-s1">employeeList</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
}</pre></div>
<p dir="auto">此时分页的数据就应该是年龄在 20~50 岁之间，且 gender 值为 1 的员工信息，然后再对这些数据进行分页。</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">乐观锁</h2><a id="user-content-乐观锁" class="anchor" aria-label="Permalink: 乐观锁" href="#乐观锁"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">当程序中出现并发访问时，就需要保证数据的一致性。以商品系统为例，现在有两个管理员均想对同一件售价为 100 元的商品进行修改，A 管理员正准备将商品售价改为 150 元，但此时出现了网络问题，导致 A 管理员的操作陷入了等待状态；此时 B 管理员也进行修改，将商品售价改为了 200 元，修改完成后 B 管理员退出了系统，此时 A 管理员的操作也生效了，这样便使得 A 管理员的操作直接覆盖了 B 管理员的操作，B 管理员后续再进行查询时会发现商品售价变为了 150 元，这样的情况是绝对不允许发生的。</p>
<p dir="auto">要想解决这一问题，可以给数据表加锁，常见的方式有两种：</p>
<ol dir="auto">
<li>乐观锁</li>
<li>悲观锁</li>
</ol>
<p dir="auto">悲观锁认为并发情况一定会发生，所以在某条数据被修改时，为了避免其它人修改，会直接对数据表进行加锁，它依靠的是数据库本身提供的锁机制（表锁、行锁、读锁、写锁）。</p>
<p dir="auto">而乐观锁则相反，它认为数据产生冲突的情况一般不会发生，所以在修改数据的时候并不会对数据表进行加锁的操作，而是在提交数据时进行校验，判断提交上来的数据是否会发生冲突，如果发生冲突，则提示用户重新进行操作，一般的实现方式为 <code>设置版本号字段</code> 。</p>
<p dir="auto">就以商品售价为例，在该表中设置一个版本号字段，让其初始为 1，此时 A 管理员和 B 管理员同时需要修改售价，它们会先读取到数据表中的内容，此时两个管理员读取到的版本号都为 1，此时 B 管理员的操作先生效了，它就会将当前数据表中对应数据的版本号与最开始读取到的版本号作一个比对，发现没有变化，于是修改就生效了，此时版本号加 1。</p>
<p dir="auto">而 A 管理员马上也提交了修改操作，但是此时的版本号为 2，与最开始读取到的版本号并不对应，这就说明数据发生了冲突，此时应该提示 A 管理员操作失败，并让 A 管理员重新查询一次数据。</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/edba75d690913bdb285f478e808d9b4cac7cbb889c9ff638564ee1e0d272b25d/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363232313430383632332e706e67"><img src="https://camo.githubusercontent.com/edba75d690913bdb285f478e808d9b4cac7cbb889c9ff638564ee1e0d272b25d/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303432363232313430383632332e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210426221408623.png" style="max-width: 100%;"></a></p>
<p dir="auto">乐观锁的优势在于采取了更加宽松的加锁机制，能够提高程序的吞吐量，适用于读操作多的场景。</p>
<p dir="auto">那么接下来我们就来模拟这一过程。</p>
<p dir="auto"><strong>1.创建一张新的数据表：</strong></p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="create table shop(
	id bigint(20) not null auto_increment,
  name varchar(30) not null,
  price int(11) default 0,
  version int(11) default 1,
  primary key(id)
);

insert into shop(id,name,price) values(1,'笔记本电脑',8000);"><pre><span class="pl-k">create</span> <span class="pl-k">table</span> <span class="pl-en">shop</span>(
	id <span class="pl-k">bigint</span>(<span class="pl-c1">20</span>) <span class="pl-k">not null</span> auto_increment,
  name <span class="pl-k">varchar</span>(<span class="pl-c1">30</span>) <span class="pl-k">not null</span>,
  price <span class="pl-k">int</span>(<span class="pl-c1">11</span>) default <span class="pl-c1">0</span>,
  version <span class="pl-k">int</span>(<span class="pl-c1">11</span>) default <span class="pl-c1">1</span>,
  <span class="pl-k">primary key</span>(id)
);

<span class="pl-k">insert into</span> shop(id,name,price) <span class="pl-k">values</span>(<span class="pl-c1">1</span>,<span class="pl-s"><span class="pl-pds">'</span>笔记本电脑<span class="pl-pds">'</span></span>,<span class="pl-c1">8000</span>);</pre></div>
<p dir="auto"><strong>2.创建实体类：</strong></p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
public class Shop {

    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Shop</span> {

    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">name</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">price</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">version</span>;
}</pre></div>
<p dir="auto"><strong>3.创建对应的 <code>Mapper</code> 接口：</strong></p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="public interface ShopMapper extends BaseMapper&lt;Shop&gt; {
}"><pre><span class="pl-k">public</span> <span class="pl-k">interface</span> <span class="pl-smi">ShopMapper</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseMapper</span>&lt;<span class="pl-smi">Shop</span>&gt; {
}</pre></div>
<p dir="auto"><strong>4.编写测试代码：</strong></p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@SpringBootTest
@MapperScan(&quot;com.wwj.mybatisplusdemo.mapper&quot;)
class MybatisplusDemoApplicationTests {

    @Autowired
    private ShopMapper shopMapper;

    /**
     * 模拟并发场景
     */
    @Test
    void contextLoads() {
        // A、B管理员读取数据
        Shop A = shopMapper.selectById(1L);
        Shop B = shopMapper.selectById(1L);
        // B管理员先修改
        B.setPrice(9000);
        int result = shopMapper.updateById(B);
        if (result == 1) {
            System.out.println(&quot;B管理员修改成功!&quot;);
        } else {
            System.out.println(&quot;B管理员修改失败!&quot;);
        }
        // A管理员后修改
        A.setPrice(8500);
        int result2 = shopMapper.updateById(A);
        if (result2 == 1) {
            System.out.println(&quot;A管理员修改成功!&quot;);
        } else {
            System.out.println(&quot;A管理员修改失败!&quot;);
        }
        // 最后查询
        System.out.println(shopMapper.selectById(1L));
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">SpringBootTest</span>
<span class="pl-c1">@</span><span class="pl-c1">MapperScan</span>(<span class="pl-s">"com.wwj.mybatisplusdemo.mapper"</span>)
<span class="pl-k">class</span> <span class="pl-smi">MybatisplusDemoApplicationTests</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Autowired</span>
    <span class="pl-k">private</span> <span class="pl-smi">ShopMapper</span> <span class="pl-s1">shopMapper</span>;

    <span class="pl-c">/**</span>
<span class="pl-c">     * 模拟并发场景</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">@</span><span class="pl-c1">Test</span>
    <span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
        <span class="pl-c">// A、B管理员读取数据</span>
        <span class="pl-smi">Shop</span> <span class="pl-s1">A</span> = <span class="pl-s1">shopMapper</span>.<span class="pl-en">selectById</span>(<span class="pl-c1">1L</span>);
        <span class="pl-smi">Shop</span> <span class="pl-s1">B</span> = <span class="pl-s1">shopMapper</span>.<span class="pl-en">selectById</span>(<span class="pl-c1">1L</span>);
        <span class="pl-c">// B管理员先修改</span>
        <span class="pl-smi">B</span>.<span class="pl-en">setPrice</span>(<span class="pl-c1">9000</span>);
        <span class="pl-smi">int</span> <span class="pl-s1">result</span> = <span class="pl-s1">shopMapper</span>.<span class="pl-en">updateById</span>(<span class="pl-s1">B</span>);
        <span class="pl-k">if</span> (<span class="pl-s1">result</span> == <span class="pl-c1">1</span>) {
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"B管理员修改成功!"</span>);
        } <span class="pl-k">else</span> {
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"B管理员修改失败!"</span>);
        }
        <span class="pl-c">// A管理员后修改</span>
        <span class="pl-smi">A</span>.<span class="pl-en">setPrice</span>(<span class="pl-c1">8500</span>);
        <span class="pl-smi">int</span> <span class="pl-s1">result2</span> = <span class="pl-s1">shopMapper</span>.<span class="pl-en">updateById</span>(<span class="pl-s1">A</span>);
        <span class="pl-k">if</span> (<span class="pl-s1">result2</span> == <span class="pl-c1">1</span>) {
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"A管理员修改成功!"</span>);
        } <span class="pl-k">else</span> {
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"A管理员修改失败!"</span>);
        }
        <span class="pl-c">// 最后查询</span>
        <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s1">shopMapper</span>.<span class="pl-en">selectById</span>(<span class="pl-c1">1L</span>));
    }
}</pre></div>
<p dir="auto">执行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="B管理员修改成功!
A管理员修改成功!
Shop(id=1, name=笔记本电脑, price=8500, version=1)"><pre><span class="pl-smi">B管理员修改成功</span>!
<span class="pl-s1">A管理员修改成功</span>!
<span class="pl-en">Shop</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">name</span>=<span class="pl-s1">笔记本电脑</span>, <span class="pl-s1">price</span>=<span class="pl-c1">8500</span>, <span class="pl-s1">version</span>=<span class="pl-c1">1</span>)</pre></div>
<p dir="auto"><strong>问题出现了，B 管理员的操作被 A 管理员覆盖，那么该如何解决这一问题呢？</strong></p>
<p dir="auto">其实 <code>MyBatisPlus</code> 已经提供了乐观锁机制，只需要在实体类中使用 <code>@Version</code> 声明版本号属性：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Data
public class Shop {

    private Long id;
    private String name;
    private Integer price;
    @Version // 声明版本号属性
    private Integer version;
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Data</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">Shop</span> {

    <span class="pl-k">private</span> <span class="pl-smi">Long</span> <span class="pl-s1">id</span>;
    <span class="pl-k">private</span> <span class="pl-smi">String</span> <span class="pl-s1">name</span>;
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">price</span>;
    <span class="pl-c1">@</span><span class="pl-c1">Version</span> <span class="pl-c">// 声明版本号属性</span>
    <span class="pl-k">private</span> <span class="pl-smi">Integer</span> <span class="pl-s1">version</span>;
}</pre></div>
<p dir="auto">然后注册乐观锁插件：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Configuration
public class MyBatisConfig {

    /**
     * 注册插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Configuration</span>
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">MyBatisConfig</span> {

    <span class="pl-c">/**</span>
<span class="pl-c">     * 注册插件</span>
<span class="pl-c">     * @return</span>
<span class="pl-c">     */</span>
    <span class="pl-c1">@</span><span class="pl-c1">Bean</span>
    <span class="pl-k">public</span> <span class="pl-smi">MybatisPlusInterceptor</span> <span class="pl-en">mybatisPlusInterceptor</span>() {
        <span class="pl-smi">MybatisPlusInterceptor</span> <span class="pl-s1">interceptor</span> = <span class="pl-k">new</span> <span class="pl-smi">MybatisPlusInterceptor</span>();
        <span class="pl-c">// 分页插件</span>
        <span class="pl-s1">interceptor</span>.<span class="pl-en">addInnerInterceptor</span>(<span class="pl-k">new</span> <span class="pl-smi">PaginationInnerInterceptor</span>(<span class="pl-smi">DbType</span>.<span class="pl-c1">MYSQL</span>));
        <span class="pl-c">// 乐观锁插件</span>
        <span class="pl-s1">interceptor</span>.<span class="pl-en">addInnerInterceptor</span>(<span class="pl-k">new</span> <span class="pl-smi">OptimisticLockerInnerInterceptor</span>());
        <span class="pl-k">return</span> <span class="pl-s1">interceptor</span>;
    }
}</pre></div>
<p dir="auto">重新执行测试代码，结果如下：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="B管理员修改成功!
A管理员修改失败!
Shop(id=1, name=笔记本电脑, price=9000, version=2)"><pre><span class="pl-smi">B管理员修改成功</span>!
<span class="pl-s1">A管理员修改失败</span>!
<span class="pl-en">Shop</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">name</span>=<span class="pl-s1">笔记本电脑</span>, <span class="pl-s1">price</span>=<span class="pl-c1">9000</span>, <span class="pl-s1">version</span>=<span class="pl-c1">2</span>)</pre></div>
<p dir="auto">此时 A 管理员的修改就失败了，它需要重新读取最新的数据才能再次进行修改。</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">条件构造器</h2><a id="user-content-条件构造器" class="anchor" aria-label="Permalink: 条件构造器" href="#条件构造器"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">在分页插件中我们简单地使用了一下条件构造器（<code>Wrapper</code>），下面我们来详细了解一下。
先来看看 <code>Wrapper</code> 的继承体系：
<a target="_blank" rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/974e52001f5f92df99b0987a16491b732a615f8c076758a0f63d67df88caf469/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038333934343331352e706e67"><img src="https://camo.githubusercontent.com/974e52001f5f92df99b0987a16491b732a615f8c076758a0f63d67df88caf469/68747470733a2f2f696d672d626c6f672e6373646e696d672e636e2f32303231303531393038333934343331352e706e67" alt="" data-canonical-src="https://img-blog.csdnimg.cn/20210519083944315.png" style="max-width: 100%;"></a>
分别介绍一下它们的作用：</p>
<ul dir="auto">
<li><code>Wrapper</code>：条件构造器抽象类，最顶端的父类
<ul dir="auto">
<li><code>AbstractWrapper</code>：查询条件封装抽象类，生成 SQL 的 where 条件
<ul dir="auto">
<li><code>QueryWrapper</code>：用于对象封装</li>
<li><code>UpdateWrapper</code>：用于条件封装</li>
</ul>
</li>
<li><code>AbstractLambdaWrapper</code>：Lambda 语法使用 Wrapper
<ul dir="auto">
<li><code>LambdaQueryWrapper</code>：用于对象封装，使用 Lambda 语法</li>
<li><code>LambdaUpdateWrapper</code>：用于条件封装，使用 Lambda 语法</li>
</ul>
</li>
</ul>
</li>
</ul>
<p dir="auto">通常我们使用的都是 <code>QueryWrapper</code> 和 <code>UpdateWrapper</code>，若是想使用 Lambda 语法来编写，也可以使用 <code>LambdaQueryWrapper</code> 和 <code>LambdaUpdateWrapper</code>，通过这些条件构造器，我们能够很方便地来实现一些复杂的筛选操作，比如：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@SpringBootTest
@MapperScan(&quot;com.wwj.mybatisplusdemo.mapper&quot;)
class MybatisplusDemoApplicationTests {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Test
    void contextLoads() {
        // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息
        QueryWrapper&lt;Employee&gt; wrapper = new QueryWrapper&lt;&gt;();
        wrapper.like(&quot;last_name&quot;, &quot;j&quot;);
        wrapper.gt(&quot;age&quot;, 20);
        wrapper.isNotNull(&quot;email&quot;);
        List&lt;Employee&gt; list = employeeMapper.selectList(wrapper);
        list.forEach(System.out::println);
    }
}"><pre><span class="pl-c1">@</span><span class="pl-c1">SpringBootTest</span>
<span class="pl-c1">@</span><span class="pl-c1">MapperScan</span>(<span class="pl-s">"com.wwj.mybatisplusdemo.mapper"</span>)
<span class="pl-k">class</span> <span class="pl-smi">MybatisplusDemoApplicationTests</span> {

    <span class="pl-c1">@</span><span class="pl-c1">Autowired</span>
    <span class="pl-k">private</span> <span class="pl-smi">EmployeeMapper</span> <span class="pl-s1">employeeMapper</span>;

    <span class="pl-c1">@</span><span class="pl-c1">Test</span>
    <span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
        <span class="pl-c">// 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息</span>
        <span class="pl-smi">QueryWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">wrapper</span> = <span class="pl-k">new</span> <span class="pl-smi">QueryWrapper</span>&lt;&gt;();
        <span class="pl-s1">wrapper</span>.<span class="pl-en">like</span>(<span class="pl-s">"last_name"</span>, <span class="pl-s">"j"</span>);
        <span class="pl-s1">wrapper</span>.<span class="pl-en">gt</span>(<span class="pl-s">"age"</span>, <span class="pl-c1">20</span>);
        <span class="pl-s1">wrapper</span>.<span class="pl-en">isNotNull</span>(<span class="pl-s">"email"</span>);
        <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">list</span> = <span class="pl-s1">employeeMapper</span>.<span class="pl-en">selectList</span>(<span class="pl-s1">wrapper</span>);
        <span class="pl-s1">list</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
    }
}</pre></div>
<p dir="auto">运行结果：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Employee(id=1, lastName=jack, email=jack@qq.com, age=35, gmtCreate=2021-04-24T21:14:18, gmtModified=2021-04-24T21:14:18, deleted=0)"><pre><span class="pl-en">Employee</span>(<span class="pl-s1">id</span>=<span class="pl-c1">1</span>, <span class="pl-s1">lastName</span>=<span class="pl-s1">jack</span>, <span class="pl-s1">email</span>=<span class="pl-smi">jack</span><span class="pl-c1">@</span><span class="pl-s1">qq</span>.<span class="pl-s1">com</span>, <span class="pl-s1">age</span>=<span class="pl-c1">35</span>, <span class="pl-s1">gmtCreate</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">gmtModified</span>=<span class="pl-c1">2021</span>-<span class="pl-c1">04</span>-<span class="pl-c1">24</span><span class="pl-c1">T21</span>:<span class="pl-c1">14</span>:<span class="pl-c1">18</span>, <span class="pl-s1">deleted</span>=<span class="pl-c1">0</span>)</pre></div>
<p dir="auto">条件构造器提供了丰富的条件方法帮助我们进行条件的构造，比如 <code>like</code> 方法会为我们建立模糊查询，查看一下控制台输出的 SQL：</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="==&gt;  Preparing: SELECT id,last_name,email,age,gmt_create,gmt_modified,is_deleted AS deleted FROM tbl_employee WHERE is_deleted=0 AND (last_name LIKE ? AND age &gt; ? AND email IS NOT NULL)
==&gt; Parameters: %j%(String), 20(Integer)"><pre><span class="pl-k">==&gt;</span>  Preparing: <span class="pl-k">SELECT</span> id,last_name,email,age,gmt_create,gmt_modified,is_deleted <span class="pl-k">AS</span> deleted <span class="pl-k">FROM</span> tbl_employee <span class="pl-k">WHERE</span> is_deleted<span class="pl-k">=</span><span class="pl-c1">0</span> <span class="pl-k">AND</span> (last_name <span class="pl-k">LIKE</span> ? <span class="pl-k">AND</span> age <span class="pl-k">&gt;</span> ? <span class="pl-k">AND</span> email <span class="pl-k">IS NOT NULL</span>)
<span class="pl-k">==&gt;</span> Parameters: %j%(String), <span class="pl-c1">20</span>(<span class="pl-k">Integer</span>)</pre></div>
<p dir="auto">可以看到它是对 <code>j</code> 的前后都加上了 <code>%</code> ，若是只想查询以 <code>j</code> 开头的名字，则可以使用 <code>likeRight</code> 方法，若是想查询以 <code>j</code> 结尾的名字，，则使用 <code>likeLeft</code> 方法。</p>
<p dir="auto">年龄的比较也是如此， <code>gt</code> 是大于指定值，若是小于则调用 <code>lt</code> ，大于等于调用 <code>ge</code> ，小于等于调用 <code>le</code> ，不等于调用 <code>ne</code> ，还可以使用 <code>between</code> 方法实现这一过程，相关的其它方法都可以查阅源码进行学习。</p>
<p dir="auto">因为这些方法返回的其实都是自身实例，所以可使用链式编程：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息
    QueryWrapper&lt;Employee&gt; wrapper = new QueryWrapper&lt;Employee&gt;()
        .likeLeft(&quot;last_name&quot;, &quot;j&quot;)
        .gt(&quot;age&quot;, 20)
        .isNotNull(&quot;email&quot;);
    List&lt;Employee&gt; list = employeeMapper.selectList(wrapper);
    list.forEach(System.out::println);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-c">// 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息</span>
    <span class="pl-smi">QueryWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">wrapper</span> = <span class="pl-k">new</span> <span class="pl-smi">QueryWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt;()
        .<span class="pl-en">likeLeft</span>(<span class="pl-s">"last_name"</span>, <span class="pl-s">"j"</span>)
        .<span class="pl-en">gt</span>(<span class="pl-s">"age"</span>, <span class="pl-c1">20</span>)
        .<span class="pl-en">isNotNull</span>(<span class="pl-s">"email"</span>);
    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">list</span> = <span class="pl-s1">employeeMapper</span>.<span class="pl-en">selectList</span>(<span class="pl-s1">wrapper</span>);
    <span class="pl-s1">list</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
}</pre></div>
<p dir="auto">也可以使用 <code>LambdaQueryWrapper</code> 实现：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    // 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息
    LambdaQueryWrapper&lt;Employee&gt; wrapper = new LambdaQueryWrapper&lt;Employee&gt;()
        .like(Employee::getLastName,&quot;j&quot;)
        .gt(Employee::getAge,20)
        .isNotNull(Employee::getEmail);
    List&lt;Employee&gt; list = employeeMapper.selectList(wrapper);
    list.forEach(System.out::println);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-c">// 查询名字中包含'j'，年龄大于20岁，邮箱不为空的员工信息</span>
    <span class="pl-smi">LambdaQueryWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">wrapper</span> = <span class="pl-k">new</span> <span class="pl-smi">LambdaQueryWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt;()
        .<span class="pl-en">like</span>(<span class="pl-smi">Employee</span>::<span class="pl-s1">getLastName</span>,<span class="pl-s">"j"</span>)
        .<span class="pl-en">gt</span>(<span class="pl-smi">Employee</span>::<span class="pl-s1">getAge</span>,<span class="pl-c1">20</span>)
        .<span class="pl-en">isNotNull</span>(<span class="pl-smi">Employee</span>::<span class="pl-s1">getEmail</span>);
    <span class="pl-smi">List</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">list</span> = <span class="pl-s1">employeeMapper</span>.<span class="pl-en">selectList</span>(<span class="pl-s1">wrapper</span>);
    <span class="pl-s1">list</span>.<span class="pl-en">forEach</span>(<span class="pl-smi">System</span>.<span class="pl-s1">out</span>::<span class="pl-s1">println</span>);
}</pre></div>
<p dir="auto">这种方式的好处在于对字段的设置不是硬编码，而是采用方法引用的形式，效果与 <code>QueryWrapper</code> 是一样的。</p>
<p dir="auto"><code>UpdateWrapper</code> 与 <code>QueryWrapper</code> 不同，它的作用是封装更新内容的，比如：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@Test
void contextLoads() {
    UpdateWrapper&lt;Employee&gt; wrapper = new UpdateWrapper&lt;Employee&gt;()
        .set(&quot;age&quot;, 50)
        .set(&quot;email&quot;, &quot;emp@163.com&quot;)
        .like(&quot;last_name&quot;, &quot;j&quot;)
        .gt(&quot;age&quot;, 20);
    employeeMapper.update(null, wrapper);
}"><pre><span class="pl-c1">@</span><span class="pl-c1">Test</span>
<span class="pl-smi">void</span> <span class="pl-en">contextLoads</span>() {
    <span class="pl-smi">UpdateWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt; <span class="pl-s1">wrapper</span> = <span class="pl-k">new</span> <span class="pl-smi">UpdateWrapper</span>&lt;<span class="pl-smi">Employee</span>&gt;()
        .<span class="pl-en">set</span>(<span class="pl-s">"age"</span>, <span class="pl-c1">50</span>)
        .<span class="pl-en">set</span>(<span class="pl-s">"email"</span>, <span class="pl-s">"emp@163.com"</span>)
        .<span class="pl-en">like</span>(<span class="pl-s">"last_name"</span>, <span class="pl-s">"j"</span>)
        .<span class="pl-en">gt</span>(<span class="pl-s">"age"</span>, <span class="pl-c1">20</span>);
    <span class="pl-s1">employeeMapper</span>.<span class="pl-en">update</span>(<span class="pl-c1">null</span>, <span class="pl-s1">wrapper</span>);
}</pre></div>
<p dir="auto">将名字中包含 <code>j</code> 且年龄大于 20 岁的员工年龄改为 50，邮箱改为 <a href="mailto:emp@163.com">emp@163.com</a>，<code>UpdateWrapper</code> 不仅能够封装更新内容，也能作为查询条件，所以在更新数据时可以直接构造一个 <code>UpdateWrapper</code> 来设置更新内容和条件。</p>
</article></div><div class="d-none"></div></section></div></div></div> </div> <!-- --> </div></div></div></div></div></div><div class="ScrollMarksContainer-module__scrollMarksContainer__Eu7uU" id="find-result-marks-container"></div><div class="d-none"></div><div class="d-none"></div></div> <!-- --> <!-- --> </div>
</react-app>




  </div>

</turbo-frame>

    </main>
  </div>

  </div>

          <footer class="footer f6 color-fg-muted color-border-subtle tmp-pt-7 tmp-pb-6 p-responsive" role="contentinfo"  >
  <h2 class='sr-only'>Footer</h2>

  


  <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap">
    <div class="d-flex flex-items-center flex-shrink-0 mx-2">
      <a aria-label="GitHub Homepage" class="footer-octicon mr-2" href="https://github.com">
        <svg aria-hidden="true" data-component="Octicon" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github">
    <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path>
</svg>
</a>
      <span>
        &copy; 2026 GitHub,&nbsp;Inc.
      </span>
    </div>

    <nav aria-label="Footer">
      <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3>

      <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading">


          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a>
          </li>


            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a>
            </li>

            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a>
            </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to community&quot;,&quot;label&quot;:&quot;text:community&quot;}" href="https://github.community/" data-view-component="true" class="Link--secondary Link">Community</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a>
          </li>

          
<li class="mx-2" >
  <cookie-consent-link>
    <button
      type="button"
      class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent"
      data-action="click:cookie-consent-link#showConsentManagement"
      data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}"
    >
      Manage cookies
    </button>
  </cookie-consent-link>
</li>

  <li class="mx-2">
    <cookie-consent-link>
      <button
        type="button"
        class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent text-left"
        data-action="click:cookie-consent-link#showConsentManagement"
        data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}"
      >
        Do not share my personal information
      </button>
    </cookie-consent-link>
  </li>

      </ul>
    </nav>
  </div>
</footer>



    <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999"
      data-locale="en"
      data-initial-cookie-consent-allowed=""
      data-cookie-consent-required="true"
    ></ghcc-consent>




  <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden>
    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    You can’t perform that action at this time.
  </div>

    <template id="site-details-dialog">
  <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open>
    <summary role="button" aria-label="Close dialog"></summary>
    <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal">
      <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog>
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
      </button>
      <div class="octocat-spinner tmp-my-6 js-details-dialog-spinner"></div>
    </details-dialog>
  </details>
</template>

    <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;">
  <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;">
  </div>
</div>

    <template id="snippet-clipboard-copy-button">
  <div class="zeroclipboard-container position-absolute right-0 top-0">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2 tmp-m-2">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2 tmp-m-2">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>
<template id="snippet-clipboard-copy-button-unpositioned">
  <div class="zeroclipboard-container">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>




    </div>
    <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div>
    <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div>
  </body>
</html>

