java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java数据库到接口实现

Java后端开发标准流程之从数据库到接口的完整实现方法

作者:Filotimo_

后端开发是指开发基于服务器端的软件应用程序,也称为系统的后台或服务器端编程,下面这篇文章主要介绍了Java后端开发标准流程之从数据库到接口的完整实现方法,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在实际的Java后端开发中,我们通常会遵循一个标准的开发流程,确保代码结构清晰、层次分明、易于维护。本文将以一个图书管理系统为例,详细介绍从数据库设计到接口实现的完整流程。

完整开发流程

第1步:创建数据表
       ↓
第2步:创建Entity实体类
       ↓
第3步:创建DTO对象
       ↓
第4步:创建Repository数据访问层
       ↓
第5步:创建Service业务逻辑层
       ↓
第6步:创建Controller控制器层
       ↓
第7步:创建SQL配置类(可选,复杂查询使用)

第1步:创建数据表

首先在数据库中创建表结构,这是整个系统的数据基础。

-- 图书表
CREATE TABLE book (
    id VARCHAR(32) PRIMARY KEY,
    book_name VARCHAR(100) NOT NULL,
    author VARCHAR(50),
    isbn VARCHAR(20) UNIQUE,
    price DECIMAL(10, 2),
    stock INT DEFAULT 0,
    publish_date DATE,
    deleted INT DEFAULT 0,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 图书借阅记录表
CREATE TABLE book_borrow (
    id VARCHAR(32) PRIMARY KEY,
    book_id VARCHAR(32),
    reader_name VARCHAR(50),
    borrow_date DATE,
    return_date DATE,
    status INT DEFAULT 0,  -- 0-借阅中 1-已归还
    deleted INT DEFAULT 0,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (book_id) REFERENCES book(id)
);

设计要点:

第2步:创建Entity实体类

Entity类对应数据库表结构,用于ORM映射。

package com.example.library.entity;

import lombok.Data;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 图书实体类
 * 对应数据库表:book
 */
@Data
@Entity
@Table(name = "book")
public class Book {
    
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    @Column(name = "id", nullable = false)
    private String id;
    
    @Column(name = "book_name", nullable = false)
    private String bookName;
    
    @Column(name = "author")
    private String author;
    
    @Column(name = "isbn", unique = true)
    private String isbn;
    
    @Column(name = "price")
    private BigDecimal price;
    
    @Column(name = "stock")
    private Integer stock;
    
    @Column(name = "publish_date")
    private Date publishDate;
    
    @Column(name = "deleted")
    private Integer deleted;
    
    @Column(name = "create_time")
    private Date createTime;
    
    @Column(name = "update_time")
    private Date updateTime;
}

Entity的作用:

第3步:创建DTO对象

DTO(Data Transfer Object)用于前后端数据传输,与Entity分离。

3.1 请求DTO(接收前端参数)

package com.example.library.dto;

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

/**
 * 新增图书请求DTO
 */
@Data
@ApiModel("新增图书请求")
public class AddBookDTO {
    
    @ApiModelProperty("图书名称")
    private String bookName;
    
    @ApiModelProperty("作者")
    private String author;
    
    @ApiModelProperty("ISBN")
    private String isbn;
    
    @ApiModelProperty("价格")
    private BigDecimal price;
    
    @ApiModelProperty("库存数量")
    private Integer stock;
    
    @ApiModelProperty("出版日期")
    private String publishDate;
}

3.2 响应DTO(返回数据给前端)

package com.example.library.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;

/**
 * 图书详情响应DTO
 */
@Data
@ApiModel("图书详情")
public class BookDetailDTO {
    
    @ApiModelProperty("图书ID")
    private String id;
    
    @ApiModelProperty("图书名称")
    private String bookName;
    
    @ApiModelProperty("作者")
    private String author;
    
    @ApiModelProperty("价格")
    private BigDecimal price;
    
    @ApiModelProperty("库存状态")
    private String stockStatus;  // "充足"、"紧张"、"缺货"
    
    @ApiModelProperty("是否可借")
    private Boolean borrowable;
}

为什么要用DTO?

第4步:创建Repository数据访问层

Repository负责与数据库交互,提供基本的CRUD操作。

package com.example.library.repository;

import com.example.library.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;

/**
 * 图书数据访问层
 */
public interface BookRepository extends JpaRepository<Book, String> {
    
    /**
     * 根据ISBN查找图书
     */
    Book findByIsbn(String isbn);
    
    /**
     * 根据作者模糊查询
     */
    List<Book> findByAuthorContaining(String author);
    
    /**
     * 查询库存不足的图书
     */
    @Query("SELECT b FROM Book b WHERE b.stock < :threshold AND b.deleted = 0")
    List<Book> findLowStockBooks(@Param("threshold") Integer threshold);
    
    /**
     * 统计图书总数
     */
    @Query("SELECT COUNT(b) FROM Book b WHERE b.deleted = 0")
    Long countByDeleted();
}

Repository的特点:

第5步:创建Service业务逻辑层

Service负责业务逻辑处理,连接Controller和Repository。

5.1 Service接口

package com.example.library.service;
import com.example.library.dto.AddBookDTO;
import com.example.library.dto.BookDetailDTO;
import com.example.library.entity.Book;
import java.util.List;
/**
 * 图书业务逻辑接口
 */
public interface BookService {
    /**
     * 新增图书
     */
    boolean addBook(AddBookDTO dto);
    /**
     * 获取图书详情
     */
    BookDetailDTO getBookDetail(String bookId);
    /**
     * 借阅图书
     */
    boolean borrowBook(String bookId, String readerName);
    /**
     * 获取库存不足的图书列表
     */
    List<Book> getLowStockBooks(Integer threshold);
}

5.2 Service实现类

package com.example.library.service.impl;

import com.example.library.dto.AddBookDTO;
import com.example.library.dto.BookDetailDTO;
import com.example.library.entity.Book;
import com.example.library.repository.BookRepository;
import com.example.library.service.BookService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 图书业务逻辑实现
 */
@Transactional
@Log4j2
@Service
public class BookServiceImpl implements BookService {
    
    @Autowired
    private BookRepository bookRepository;
    
    @Override
    public boolean addBook(AddBookDTO dto) {
        try {
            // 1. 检查ISBN是否已存在
            Book existingBook = bookRepository.findByIsbn(dto.getIsbn());
            if (existingBook != null) {
                log.warn("ISBN已存在: {}", dto.getIsbn());
                return false;
            }
            
            // 2. 创建图书实体
            Book book = new Book();
            book.setId(UUID.randomUUID().toString());
            book.setBookName(dto.getBookName());
            book.setAuthor(dto.getAuthor());
            book.setIsbn(dto.getIsbn());
            book.setPrice(dto.getPrice());
            book.setStock(dto.getStock());
            book.setDeleted(0);
            book.setCreateTime(new Date());
            book.setUpdateTime(new Date());
            
            // 3. 保存到数据库
            bookRepository.save(book);
            return true;
        } catch (Exception e) {
            log.error("新增图书失败", e);
            return false;
        }
    }
    
    @Override
    public BookDetailDTO getBookDetail(String bookId) {
        // 1. 查询图书
        Book book = bookRepository.findById(bookId).orElse(null);
        if (book == null) {
            return null;
        }
        
        // 2. Entity转DTO
        BookDetailDTO dto = new BookDetailDTO();
        dto.setId(book.getId());
        dto.setBookName(book.getBookName());
        dto.setAuthor(book.getAuthor());
        dto.setPrice(book.getPrice());
        
        // 3. 计算库存状态
        if (book.getStock() == 0) {
            dto.setStockStatus("缺货");
            dto.setBorrowable(false);
        } else if (book.getStock() < 5) {
            dto.setStockStatus("紧张");
            dto.setBorrowable(true);
        } else {
            dto.setStockStatus("充足");
            dto.setBorrowable(true);
        }
        
        return dto;
    }
    
    @Override
    public boolean borrowBook(String bookId, String readerName) {
        try {
            // 1. 查询图书
            Book book = bookRepository.findById(bookId).orElse(null);
            if (book == null) {
                log.warn("图书不存在: {}", bookId);
                return false;
            }
            
            // 2. 检查库存
            if (book.getStock() <= 0) {
                log.warn("库存不足: {}", book.getBookName());
                return false;
            }
            
            // 3. 扣减库存
            book.setStock(book.getStock() - 1);
            book.setUpdateTime(new Date());
            bookRepository.save(book);
            
            // 4. 创建借阅记录(省略)
            // ...
            
            return true;
        } catch (Exception e) {
            log.error("借阅图书失败", e);
            return false;
        }
    }
    
    @Override
    public List<Book> getLowStockBooks(Integer threshold) {
        return bookRepository.findLowStockBooks(threshold);
    }
}

Service的职责:

第6步:创建Controller控制器层

Controller负责接收HTTP请求,调用Service处理,返回响应。

package com.example.library.controller;

import com.example.library.dto.AddBookDTO;
import com.example.library.dto.BookDetailDTO;
import com.example.library.entity.Book;
import com.example.library.service.BookService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/**
 * 图书管理接口
 */
@Log4j2
@RestController
@RequestMapping("/api/book")
@Api(tags = "图书管理")
public class BookController {
    
    @Autowired
    private BookService bookService;
    
    /**
     * 新增图书
     * POST /api/book/add
     */
    @PostMapping("/add")
    @ApiOperation("新增图书")
    public boolean addBook(@RequestBody AddBookDTO dto) {
        log.info("新增图书: {}", dto.getBookName());
        return bookService.addBook(dto);
    }
    
    /**
     * 获取图书详情
     * GET /api/book/detail/{id}
     */
    @GetMapping("/detail/{id}")
    @ApiOperation("获取图书详情")
    public BookDetailDTO getBookDetail(@PathVariable String id) {
        log.info("查询图书详情: {}", id);
        return bookService.getBookDetail(id);
    }
    
    /**
     * 借阅图书
     * POST /api/book/borrow
     */
    @PostMapping("/borrow")
    @ApiOperation("借阅图书")
    public boolean borrowBook(@RequestParam String bookId, 
                              @RequestParam String readerName) {
        log.info("借阅图书: bookId={}, reader={}", bookId, readerName);
        return bookService.borrowBook(bookId, readerName);
    }
    
    /**
     * 获取库存不足的图书
     * GET /api/book/low-stock
     */
    @GetMapping("/low-stock")
    @ApiOperation("获取库存不足的图书")
    public List<Book> getLowStockBooks(@RequestParam(defaultValue = "5") Integer threshold) {
        log.info("查询库存不足图书: threshold={}", threshold);
        return bookService.getLowStockBooks(threshold);
    }
}

Controller的职责:

第7步:创建SQL配置类(可选)

对于复杂的统计查询、多表关联,可以使用YAML配置SQL,提高可维护性。

7.1 YAML配置文件

# src/main/resources/sql/book-sql.yml
book:
  # 图书借阅统计
  borrow-statistics:
    columns: |
      SELECT 
          b.book_name,
          b.author,
          COUNT(bb.id) AS borrow_count,
          SUM(CASE WHEN bb.status = 0 THEN 1 ELSE 0 END) AS borrowing_count
    tables: |
      FROM book b
      LEFT JOIN book_borrow bb ON b.id = bb.book_id AND bb.deleted = 0
    condition: |
      WHERE b.deleted = 0
        AND b.publish_date &gt;= :startDate
      GROUP BY b.id, b.book_name, b.author
      ORDER BY borrow_count DESC
  
  # 热门图书排行
  popular-books:
    columns: |
      SELECT 
          b.id,
          b.book_name,
          b.author,
          COUNT(bb.id) AS borrow_times
    tables: |
      FROM book b
      INNER JOIN book_borrow bb ON b.id = bb.book_id
    condition: |
      WHERE b.deleted = 0 
        AND bb.borrow_date &gt;= :startDate
        AND bb.borrow_date &lt;= :endDate
      GROUP BY b.id
      ORDER BY borrow_times DESC
      LIMIT 10

7.2 SQL配置类

package com.example.library.sql;

import com.gri.iot.common.sourceloader.YamlPropertySourceFacetory;
import com.gri.iot.common.sql.SqlBody;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * 图书SQL配置类
 */
@Data
@PropertySource(value = "classpath:/sql/book-sql.yml", factory = YamlPropertySourceFacetory.class)
@Configuration
@ConfigurationProperties(prefix = "book")
public class BookSqlConfig {
    
    /**
     * 图书借阅统计
     */
    private SqlBody borrowStatistics;
    
    /**
     * 热门图书排行
     */
    private SqlBody popularBooks;
}

7.3 使用SQL配置

@Service
public class BookReportServiceImpl implements BookReportService {
    
    @Autowired
    private BookSqlConfig bookSqlConfig;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public List<Map<String, Object>> getBorrowStatistics(String startDate) {
        // 1. 获取SQL配置
        SqlBody sqlBody = bookSqlConfig.getBorrowStatistics();
        
        // 2. 组装SQL
        String sql = sqlBody.getColumns() + 
                    sqlBody.getTables() + 
                    sqlBody.getCondition();
        
        // 3. 执行查询
        return jdbcTemplate.queryForList(sql, startDate);
    }
}

什么时候用YAML配置SQL?

什么时候用JPA?

各层之间的调用关系

┌─────────────────────────────────────────────────────────┐
│  前端(Vue/React/小程序)                                │
└──────────────────────┬──────────────────────────────────┘
                       │ HTTP请求
                       ▼
┌─────────────────────────────────────────────────────────┐
│  Controller层(控制器)                                   │
│  - 接收请求参数                                          │
│  - 调用Service                                           │
│  - 返回响应                                              │
└──────────────────────┬──────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────┐
│  Service层(业务逻辑)                                    │
│  - 业务逻辑处理                                          │
│  - 事务管理                                              │
│  - Entity ↔ DTO 转换                                     │
└─────────────┬─────────────────────────┬─────────────────┘
              │                         │
              ▼                         ▼
┌─────────────────────────┐  ┌──────────────────────────┐
│  Repository层(JPA)     │  │  SQL配置类(YAML)        │
│  - 简单CRUD              │  │  - 复杂查询               │
│  - 方法命名规则          │  │  - 统计报表               │
└────────────┬────────────┘  └────────────┬─────────────┘
             │                           │
             └───────────┬───────────────┘
                         ▼
              ┌─────────────────────────┐
              │  数据库(PostgreSQL)     │
              └─────────────────────────┘

总结

Java后端开发的标准流程可以总结为:

步骤名称作用技术选型
1数据库设计数据存储基础PostgreSQL/MySQL
2Entity实体类ORM映射,数据存储JPA @Entity
3DTO对象数据传输,前后端交互@Data, @ApiModel
4Repository层数据访问,简单CRUDJpaRepository
5Service层业务逻辑,事务管理@Service, @Transactional
6Controller层接口定义,请求处理@RestController
7SQL配置类复杂查询,统计报表YAML + SqlBody

核心原则

最佳实践

到此这篇关于Java后端开发标准流程之从数据库到接口的完整实现方法的文章就介绍到这了,更多相关Java数据库到接口实现内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文