• Spring Data JDBC结合MyBatis、MySQL 和 Thymeleaf 实现分页、排序和全字段LIKE过滤/搜索功能


        在本教程中,您将学习使用 Spring Data JDBC结合MyBatis、MySQL 和 Thymeleaf 为现有 Spring Boot 应用程序实现分页、排序和过滤/搜索功能。

     

     

    pom.xml

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    3. <modelVersion>4.0.0modelVersion>
    4. <parent>
    5. <groupId>org.springframework.bootgroupId>
    6. <artifactId>spring-boot-starter-parentartifactId>
    7. <version>2.7.4version>
    8. <relativePath/>
    9. parent>
    10. <groupId>net.codejavagroupId>
    11. <artifactId>ProductManagerSpringDataJdbcMyBatisartifactId>
    12. <version>0.0.1-SNAPSHOTversion>
    13. <name>ProductManagerSpringDataJdbcMyBatisname>
    14. <description>Spring Boot Web Appdescription>
    15. <properties>
    16. <java.version>17java.version>
    17. properties>
    18. <dependencies>
    19. <dependency>
    20. <groupId>org.springframework.bootgroupId>
    21. <artifactId>spring-boot-starter-data-jdbcartifactId>
    22. dependency>
    23. <dependency>
    24. <groupId>org.springframework.bootgroupId>
    25. <artifactId>spring-boot-starter-thymeleafartifactId>
    26. dependency>
    27. <dependency>
    28. <groupId>org.springframework.bootgroupId>
    29. <artifactId>spring-boot-starter-webartifactId>
    30. dependency>
    31. <dependency>
    32. <groupId>org.springframework.bootgroupId>
    33. <artifactId>spring-boot-starter-testartifactId>
    34. <scope>testscope>
    35. dependency>
    36. <dependency>
    37. <groupId>mysqlgroupId>
    38. <artifactId>mysql-connector-javaartifactId>
    39. <scope>runtimescope>
    40. dependency>
    41. <dependency>
    42. <groupId>org.springframework.bootgroupId>
    43. <artifactId>spring-boot-devtoolsartifactId>
    44. dependency>
    45. <dependency>
    46. <groupId>org.projectlombokgroupId>
    47. <artifactId>lombokartifactId>
    48. dependency>
    49. <dependency>
    50. <groupId>org.mybatis.spring.bootgroupId>
    51. <artifactId>mybatis-spring-boot-starterartifactId>
    52. <version>2.2.2version>
    53. dependency>
    54. <dependency>
    55. <groupId>org.mybatis.generatorgroupId>
    56. <artifactId>mybatis-generator-coreartifactId>
    57. <version>1.4.1version>
    58. dependency>
    59. dependencies>
    60. <build>
    61. <plugins>
    62. <plugin>
    63. <groupId>org.springframework.bootgroupId>
    64. <artifactId>spring-boot-maven-pluginartifactId>
    65. plugin>
    66. plugins>
    67. build>
    68. project>

    application.properties

    1. spring.jpa.hibernate.ddl-auto=none
    2. spring.datasource.url=jdbc:mysql://localhost:3306/sales?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    3. spring.datasource.username=root
    4. spring.datasource.password=root
    5. #logging.level.root=
    6. #debug=true
    7. logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG
    8. logging.level.net.codejava=DEBUG

    ProductManagerApplication.java

    1. package net.codejava;
    2. import org.apache.ibatis.type.MappedTypes;
    3. import org.mybatis.spring.annotation.MapperScan;
    4. import org.springframework.boot.SpringApplication;
    5. import org.springframework.boot.autoconfigure.SpringBootApplication;
    6. @MappedTypes(Product.class)
    7. @MapperScan("net.codejava")
    8. @SpringBootApplication
    9. public class ProductManagerApplication {
    10. public static void main(String[] args) {
    11. SpringApplication.run(ProductManagerApplication.class, args);
    12. }
    13. }

    Product.java

    1. package net.codejava;
    2. import org.springframework.data.annotation.Id;
    3. import org.springframework.data.relational.core.mapping.Column;
    4. import org.springframework.data.relational.core.mapping.Table;
    5. import lombok.Data;
    6. @Table("product")
    7. @Data // lomok
    8. public class Product {
    9. @Id
    10. private Long id;
    11. private String name;
    12. private String brand;
    13. private String madein;
    14. private float price;
    15. protected Product() {
    16. }
    17. public Long getId() {
    18. return id;
    19. }
    20. public void setId(Long id) {
    21. this.id = id;
    22. }
    23. public String getName() {
    24. return name;
    25. }
    26. public void setName(String name) {
    27. this.name = name;
    28. }
    29. public String getBrand() {
    30. return brand;
    31. }
    32. public void setBrand(String brand) {
    33. this.brand = brand;
    34. }
    35. public String getMadein() {
    36. return madein;
    37. }
    38. public void setMadein(String madein) {
    39. this.madein = madein;
    40. }
    41. public float getPrice() {
    42. return price;
    43. }
    44. public void setPrice(float price) {
    45. this.price = price;
    46. }
    47. }

    ProductRepository.java

    1. package net.codejava;
    2. import org.springframework.data.domain.Page;
    3. import org.springframework.data.domain.Pageable;
    4. import org.springframework.data.repository.PagingAndSortingRepository;
    5. import org.springframework.stereotype.Repository;
    6. @Repository
    7. public interface ProductRepository extends PagingAndSortingRepository, ProductRepositoryCustom {
    8. Page findAllByNameContaining(String name, Pageable pageable);
    9. Page findAllByNameLikeOrBrandLikeOrMadeinLike(String name, String brand, String madein, Pageable pageable);
    10. }

    ProductRepositoryCustom.java

    1. package net.codejava;
    2. import org.springframework.data.domain.Page;
    3. import org.springframework.data.domain.Pageable;
    4. public interface ProductRepositoryCustom {
    5. public Page findAllByContaining(String keyword, Pageable page);
    6. }

    ProductMapper.java

    1. package net.codejava;
    2. import java.util.List;
    3. import org.apache.ibatis.annotations.Delete;
    4. import org.apache.ibatis.annotations.Insert;
    5. import org.apache.ibatis.annotations.Param;
    6. import org.apache.ibatis.annotations.Result;
    7. import org.apache.ibatis.annotations.Results;
    8. import org.apache.ibatis.annotations.Select;
    9. import org.apache.ibatis.annotations.SelectKey;
    10. import org.apache.ibatis.annotations.Update;
    11. import org.apache.ibatis.type.JdbcType;
    12. public interface ProductMapper {
    13. @Select("select count(*) from product WHERE CONCAT(id, ' ', name, ' ' , brand, ' ' , madein, ' ' , price) LIKE CONCAT('%',#{keyword},'%') ")
    14. int listAllSortPageContainingCount(@Param("keyword") String keyword);
    15. @Select("select * from product WHERE CONCAT(id, ' ', name, ' ' , brand, ' ' , madein, ' ' , price) LIKE CONCAT('%',#{keyword},'%') order by ${sortField} ${sortDir} LIMIT ${pageSize} OFFSET ${pageOffset}")
    16. List listAllSortPageContaining(@Param("keyword") String keyword, @Param("sortField") String sortField, @Param("sortDir") String sortDir, @Param("pageSize") Integer pageSize, @Param("pageOffset") Long pageOffset);
    17. /**
    18. * This method was generated by MyBatis Generator. This method corresponds
    19. * to the database table product
    20. *
    21. * @mbg.generated Mon Oct 31 06:50:01 CST 2022
    22. */
    23. @Delete({
    24. "delete from product",
    25. "where id = #{id,jdbcType=INTEGER}"
    26. })
    27. int deleteByPrimaryKey(Integer id);
    28. /**
    29. * This method was generated by MyBatis Generator. This method corresponds
    30. * to the database table product
    31. *
    32. * @mbg.generated Mon Oct 31 06:50:01 CST 2022
    33. */
    34. @Insert({
    35. "insert into product (name, brand, ",
    36. "madein, price)",
    37. "values (#{name,jdbcType=VARCHAR}, #{brand,jdbcType=VARCHAR}, ",
    38. "#{madein,jdbcType=VARCHAR}, #{price,jdbcType=REAL})"
    39. })
    40. @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", before = false, resultType = Integer.class)
    41. int insert(Product row);
    42. /**
    43. * This method was generated by MyBatis Generator. This method corresponds
    44. * to the database table product
    45. *
    46. * @mbg.generated Mon Oct 31 06:50:01 CST 2022
    47. */
    48. @Select({
    49. "select",
    50. "id, name, brand, madein, price",
    51. "from product",
    52. "where id = #{id,jdbcType=INTEGER}"
    53. })
    54. @Results({
    55. @Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
    56. @Result(column = "name", property = "name", jdbcType = JdbcType.VARCHAR),
    57. @Result(column = "brand", property = "brand", jdbcType = JdbcType.VARCHAR),
    58. @Result(column = "madein", property = "madein", jdbcType = JdbcType.VARCHAR),
    59. @Result(column = "price", property = "price", jdbcType = JdbcType.REAL)
    60. })
    61. Product selectByPrimaryKey(Integer id);
    62. /**
    63. * This method was generated by MyBatis Generator. This method corresponds
    64. * to the database table product
    65. *
    66. * @mbg.generated Mon Oct 31 06:50:01 CST 2022
    67. */
    68. @Select({
    69. "select",
    70. "id, name, brand, madein, price",
    71. "from product"
    72. })
    73. @Results({
    74. @Result(column = "id", property = "id", jdbcType = JdbcType.INTEGER, id = true),
    75. @Result(column = "name", property = "name", jdbcType = JdbcType.VARCHAR),
    76. @Result(column = "brand", property = "brand", jdbcType = JdbcType.VARCHAR),
    77. @Result(column = "madein", property = "madein", jdbcType = JdbcType.VARCHAR),
    78. @Result(column = "price", property = "price", jdbcType = JdbcType.REAL)
    79. })
    80. List selectAll();
    81. /**
    82. * This method was generated by MyBatis Generator. This method corresponds
    83. * to the database table product
    84. *
    85. * @mbg.generated Mon Oct 31 06:50:01 CST 2022
    86. */
    87. @Update({
    88. "update product",
    89. "set name = #{name,jdbcType=VARCHAR},",
    90. "brand = #{brand,jdbcType=VARCHAR},",
    91. "madein = #{madein,jdbcType=VARCHAR},",
    92. "price = #{price,jdbcType=REAL}",
    93. "where id = #{id,jdbcType=INTEGER}"
    94. })
    95. int updateByPrimaryKey(Product row);
    96. }

    ProductRepositoryImpl.java

    1. package net.codejava;
    2. import java.util.List;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.data.domain.Page;
    5. import org.springframework.data.domain.PageImpl;
    6. import org.springframework.data.domain.Pageable;
    7. import org.springframework.data.domain.Sort;
    8. public class ProductRepositoryImpl implements ProductRepositoryCustom {
    9. @Autowired
    10. private ProductMapper productMapper;
    11. // public ProductRepositoryImpl(ProductMapper productMapper) {
    12. // this.productMapper = productMapper;
    13. // }
    14. @Override
    15. public Page findAllByContaining(String keyword, Pageable page) {
    16. // int count = jdbcTemplate.queryForObject("SELECT count(* ) FROM product WHERE CONCAT(id, ' ', name, ' ' , brand, ' ' , madein, ' ' , price) LIKE CONCAT('%',?,'%') ", Integer.class, keyword);
    17. int count = productMapper.listAllSortPageContainingCount(keyword);
    18. Sort.Order order = !page.getSort().isEmpty() ? page.getSort().toList().get(0) : Sort.Order.by("ID");
    19. // List products = jdbcTemplate.query("SELECT * FROM product WHERE CONCAT(id, ' ', name, ' ' , brand, ' ' , madein, ' ' , price) LIKE CONCAT('%',?,'%') ORDER BY " + order.getProperty() + " "
    20. // + order.getDirection().name() + " LIMIT " + page.getPageSize() + " OFFSET " + page.getOffset(),
    21. // (rs, rowNum) -> mapUserResult(rs), keyword
    22. // );
    23. List products = productMapper.listAllSortPageContaining(keyword, order.getProperty(), order.getDirection().name(), page.getPageSize(), page.getOffset());
    24. return new PageImpl(products, page, count);
    25. }
    26. }

    ProductService.java

    1. package net.codejava;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.data.domain.Page;
    4. import org.springframework.data.domain.PageRequest;
    5. import org.springframework.data.domain.Pageable;
    6. import org.springframework.data.domain.Sort;
    7. import org.springframework.stereotype.Service;
    8. @Service
    9. public class ProductService {
    10. @Autowired
    11. private ProductRepository repo;
    12. public Page listAll(int pageNumber, String sortField, String sortDir, String keyword) {
    13. Sort sort = Sort.by(sortField);
    14. sort = sortDir.equals("asc") ? sort.ascending() : sort.descending();
    15. Pageable pageable = PageRequest.of(pageNumber - 1, 7, sort); // 7 rows per page
    16. if (keyword != null) {
    17. return repo.findAllByContaining(keyword, pageable);
    18. }
    19. return repo.findAll(pageable);
    20. }
    21. public void save(Product product) {
    22. repo.save(product);
    23. }
    24. public Product get(Long id) {
    25. return repo.findById(id).get();
    26. }
    27. public void delete(Long id) {
    28. repo.deleteById(id);
    29. }
    30. }

    AppController.java

    1. package net.codejava;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.data.domain.Page;
    4. import org.springframework.data.repository.query.Param;
    5. import org.springframework.stereotype.Controller;
    6. import org.springframework.ui.Model;
    7. import org.springframework.web.bind.annotation.GetMapping;
    8. import org.springframework.web.bind.annotation.ModelAttribute;
    9. import org.springframework.web.bind.annotation.PathVariable;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.bind.annotation.RequestMethod;
    12. import org.springframework.web.servlet.ModelAndView;
    13. import java.util.List;
    14. @Controller
    15. public class AppController {
    16. @Autowired
    17. private ProductService service;
    18. @RequestMapping("/")
    19. public String viewHomePage(Model model) {
    20. // String keyword = "reebok";
    21. String keyword = null;
    22. /*
    23. * if (keyword != null) { return listByPage(model, 1, "name", "asc", keyword); }
    24. */
    25. return listByPage(model, 1, "name", "asc", keyword);
    26. }
    27. @GetMapping("/page/{pageNumber}")
    28. public String listByPage(Model model, @PathVariable("pageNumber") int currentPage,
    29. @Param("sortField") String sortField, @Param("sortDir") String sortDir, @Param("keyword") String keyword) {
    30. Page page = service.listAll(currentPage, sortField, sortDir, keyword);
    31. long totalItems = page.getTotalElements();
    32. int totalPages = page.getTotalPages();
    33. // int currentPage = page.previousPageable().getPageNumber();
    34. List listProducts = page.getContent();
    35. model.addAttribute("totalItems", totalItems);
    36. model.addAttribute("totalPages", totalPages);
    37. model.addAttribute("currentPage", currentPage);
    38. model.addAttribute("listProducts", listProducts); // next bc of thymeleaf we make the index.html
    39. model.addAttribute("sortField", sortField);
    40. model.addAttribute("sortDir", sortDir);
    41. model.addAttribute("keyword", keyword);
    42. String reverseSortDir = sortDir.equals("asc") ? "desc" : "asc";
    43. model.addAttribute("reverseSortDir", reverseSortDir);
    44. return "index";
    45. }
    46. @RequestMapping("/new")
    47. public String showNewProductForm(Model model) {
    48. Product product = new Product();
    49. model.addAttribute("product", product);
    50. return "new_product";
    51. }
    52. @RequestMapping(value = "/save", method = RequestMethod.POST)
    53. public String saveProduct(@ModelAttribute("product") Product product) {
    54. service.save(product);
    55. return "redirect:/";
    56. }
    57. @RequestMapping("/edit/{id}")
    58. public ModelAndView showEditProductForm(@PathVariable(name = "id") Long id) {
    59. ModelAndView modelAndView = new ModelAndView("edit_product");
    60. Product product = service.get(id);
    61. modelAndView.addObject("product", product);
    62. return modelAndView;
    63. }
    64. @RequestMapping("/delete/{id}")
    65. public String deleteProduct(@PathVariable(name = "id") Long id) {
    66. service.delete(id);
    67. return "redirect:/";
    68. }
    69. }

    index.html

    1. html>
    2. <html xmlns="http://www.w3.org/1999/xhtml"
    3. xmlns:th="http://www.thymeleaf.org">
    4. <head>
    5. <meta charset="utf-8" />
    6. <title>Product Managertitle>
    7. head>
    8. <body>
    9. <div align="center">
    10. <div>
    11. <h1>Product Managerh1>
    12. <a href="/new">Create New Producta> <br />
    13. <br />
    14. div>
    15. <div>
    16. <form th:action="@{/page/1}">
    17. <input type="hidden" name="sortField" th:value="${sortField}" /> <input
    18. type="hidden" name="sortDir" th:value="${sortDir}" /> Name Filter: <input
    19. type="text" name="keyword" size="50" th:value="${keyword}" required />
    20.   <input type="submit" value="Search" />   <input
    21. type="button" value="Clear" id="btnClear" onclick="clearSearch()" />
    22. form>
    23. div>
    24. <div> div>
    25. <div>
    26. <table border="1" cellpadding="10">
    27. <thead>
    28. <tr>
    29. <th><a
    30. th:href="@{'/page/' + ${currentPage} + '?sortField=id&sortDir=' + ${reverseSortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">
    31. Product IDa>
    32. th>
    33. <th><a
    34. th:href="@{'/page/' + ${currentPage} + '?sortField=name&sortDir=' + ${reverseSortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">
    35. Namea>
    36. th>
    37. <th><a
    38. th:href="@{'/page/' + ${currentPage} + '?sortField=brand&sortDir=' + ${reverseSortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">
    39. Branda>
    40. th>
    41. <th><a
    42. th:href="@{'/page/' + ${currentPage} + '?sortField=madein&sortDir=' + ${reverseSortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">
    43. Made Ina>
    44. th>
    45. <th><a
    46. th:href="@{'/page/' + ${currentPage} + '?sortField=id&sortDir=' + ${reverseSortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">
    47. Pricea>
    48. th>
    49. <th><a>Actionsa>th>
    50. tr>
    51. thead>
    52. <tbody>
    53. <tr th:each="product : ${listProducts}">
    54. <td th:text="${product.id}">Product IDtd>
    55. <td th:text="${product.name}">Nametd>
    56. <td th:text="${product.brand}">Brandtd>
    57. <td th:text="${product.madein}">Made intd>
    58. <td th:text="${product.price}">Pricetd>
    59. <td><a th:href="@{'/edit/' + ${product.id}}">Edita>
    60.     <a th:href="@{'/delete/' + ${product.id}}">Deletea>
    61. td>
    62. tr>
    63. tbody>
    64. table>
    65. div>
    66. <div>   div>
    67. <div>
    68. Total items: [[${totalItems}]] - Page [[${currentPage}]] of
    69. [[${totalPages}]]     <a th:if="${currentPage > 1}"
    70. th:href="@{'/page/1?sortField=' + ${sortField} + '&sortDir=' + ${sortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">Firsta>
    71. <span th:unless="${currentPage > 1}">Firstspan>    <a
    72. th:if="${currentPage > 1}"
    73. th:href="@{'/page/' + ${currentPage - 1} + '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">Previousa>
    74. <span th:unless="${currentPage > 1}">Previousspan>    <span
    75. th:each="i: ${#numbers.sequence(1, totalPages)}"> <a
    76. th:if="${i != currentPage}"
    77. th:href="@{'/page/' + ${i}} + '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir} + ${keyword != null ? '&keyword=' + keyword : ''}">[[${i}]]a>
    78.     <span th:unless="${i != currentPage}">[[${i}]]span>
    79.    
    80. span> <a th:if="${currentPage < totalPages}"
    81. th:href="@{'/page/' + ${currentPage + 1} + '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">Nexta>
    82. <span th:unless="${currentPage < totalPages}">Nextspan>
    83.    <a th:if="${currentPage < totalPages}"
    84. th:href="@{'/page/' + ${totalPages} + '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir} + ${keyword != null ? '&keyword=' + keyword : ''}}">Lasta>
    85. <span th:unless="${currentPage < totalPages}">Lastspan>
    86.   
    87. div>
    88. <script type="text/javascript">
    89. function clearSearch() {
    90. window.location = "/";
    91. }
    92. script>
    93. div>
    94. body>
    95. html>

    new_product.html

    1. html>
    2. <html xmlns="http://www.w3.org/1999/xhtml"
    3. xmlns:th="http://www.thymeleaf.org">
    4. <head>
    5. <meta charset="ISO-8859-1">
    6. <title>Create new producttitle>
    7. head>
    8. <body>
    9. <div align="center">
    10. <h1>Create new producth1>
    11. <br />
    12. <form action="#" th:action="@{/save}" th:object="${product}"
    13. method="post">
    14. <table border="0" cellpadding="10">
    15. <tr>
    16. <td>Product Name:td>
    17. <td><input type="text" th:field="*{name}" />td>
    18. tr>
    19. <tr>
    20. <td>Brandtd>
    21. <td><input type="text" th:field="*{brand}" />td>
    22. tr>
    23. <tr>
    24. <td>Made in:td>
    25. <td><input type="text" th:field="*{madein}" />td>
    26. tr>
    27. <tr>
    28. <td>Price:td>
    29. <td><input type="text" th:field="*{price}" />td>
    30. tr>
    31. <tr>
    32. <td colspan="2"><button type="submit">Savebutton>td>
    33. tr>
    34. table>
    35. form>
    36. div>
    37. body>
    38. html>

    edit_product.html

    1. html>
    2. <html xmlns="http://www.w3.org/1999/xhtml"
    3. xmlns:th="http://www.thymeleaf.org">
    4. <head>
    5. <meta charset="ISO-8859-1">
    6. <title>Edit producttitle>
    7. head>
    8. <body>
    9. <div align="center">
    10. <h1>Edit producth1>
    11. <br />
    12. <form action="#" th:action="@{/save}" th:object="${product}"
    13. method="post">
    14. <table border="0" cellpadding="10">
    15. <tr>
    16. <td>Product ID:td>
    17. <td><input type="text" th:field="*{id}" readonly="readonly" />
    18. td>
    19. tr>
    20. <tr>
    21. <td>Product Name:td>
    22. <td><input type="text" th:field="*{name}" />td>
    23. tr>
    24. <tr>
    25. <td>Brandtd>
    26. <td><input type="text" th:field="*{brand}" />td>
    27. tr>
    28. <tr>
    29. <td>Made in:td>
    30. <td><input type="text" th:field="*{madein}" />td>
    31. tr>
    32. <tr>
    33. <td>Price:td>
    34. <td><input type="text" th:field="*{price}" />td>
    35. tr>
    36. <tr>
    37. <td colspan="2"><button type="submit">Savebutton>td>
    38. tr>
    39. table>
    40. form>
    41. div>
    42. body>
    43. html>

    下载:GitHub - allwaysoft/ProductManagerSpringDataJdbcMyBatis

    MyBatis同时使用注解和XML下载:GitHub - allwaysoft/ProductManagerSpringBootMyBatisAnnotationXml

  • 相关阅读:
    Web前端vueDemo—实现图片切换功能(二)
    中证1000期指上市带来的交易机会
    堆相关例子-排序最多移动k距离
    面试题 Android 如何实现自定义View 固定帧率绘制
    空间复杂度(Space Complexity)
    一个简单好用的localstorage组件store
    嵌入式C语言设计模式 --- 前言
    react合成事件——bind解决this指向——箭头函数解决this指向
    肖sir___面试就业课__非技术面试题
    33python数据分析numpy基础之union1d求数组并集
  • 原文地址:https://blog.csdn.net/allway2/article/details/127608291