# 简单示例

本节以一个简单的分页查询演示基本的代码构成。

## 数据对象（实体）

{% code title="Foo.java" %}

```java
package com.example.demo.entity;

import lombok.Data;

import javax.persistence.*;

@Entity
@Data
public class Foo {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    private Bar bar;
}
```

{% endcode %}

{% code title="Bar.java" %}

```java
package com.example.demo.entity;

import lombok.Data;
import lombok.ToString;

import javax.persistence.*;
import java.util.List;

@Entity
@Data
@ToString(exclude = "fooList")
public class Bar {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany
    private List<Foo> fooList;
}
```

{% endcode %}

{% hint style="info" %}
除基本的JPA注解之外，使用lombok提供的`@Data`注解简化POJO配置。注意使用`@ToString`注解排除可能造成循环依赖的字段。
{% endhint %}

## 数据传输对象（DTO)

{% code title="FooDto.java" %}

```java
package com.example.demo.dto;

import com.example.demo.entity.Bar;
import com.taocares.commons.beans.annotation.Nested;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel("Foo数据传输对象")
public class FooDto {

    @ApiModelProperty("唯一标识")
    private Long id;

    @ApiModelProperty("名字")
    private String name;

    @ApiModelProperty("关联的Bar")
    @Nested(thisClass = BarDto.class, thatClass = Bar.class)
    private BarDto bar;
}

```

{% endcode %}

{% code title="BarDto.java" %}

```java
package com.example.demo.dto;

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

@Data
@ApiModel("Bar数据传输对象")
public class BarDto {

    @ApiModelProperty("唯一标识")
    private Long id;

    @ApiModelProperty("名字")
    private String name;
}
```

{% endcode %}

{% hint style="info" %}
针对数据传输的需求，配置和实体字段的映射关系，定义Swagger数据模型。使用lombok简化代码。
{% endhint %}

## 数据查询对象（QO）

{% code title="FooQo.java" %}

```java
package com.example.demo.qo;

import com.taocares.commons.jpa.ConditionType;
import com.taocares.commons.jpa.QueryCondition;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel("Foo查询条件对象")
public class FooQo {

    @ApiModelProperty(value = "Foo的名字", notes = "模糊匹配开始")
    @QueryCondition(type = ConditionType.STARTS_WITH)
    private String name;

    @ApiModelProperty(value = "Bar的名字", notes = "严格匹配")
    @QueryCondition(targetField = "bar.name")
    private String barName;
}
```

{% endcode %}

{% hint style="info" %}
根据查询需求定义数据查询对象，定义Swagger数据模型。使用lombok简化代码。
{% endhint %}

## 数据持久层（Repository）

{% code title="FooRepository.java" %}

```java
package com.example.demo.repository;

import com.example.demo.entity.Foo;
import com.taocares.commons.jpa.RepositoryEnhancer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface FooRepository extends JpaRepository<Foo, Long>, JpaSpecificationExecutor<Foo>, RepositoryEnhancer {
}
```

{% endcode %}

{% hint style="info" %}
实现`JpaRepository`和`JpaSpecificationExecutor`接口即可，如果需要自定义查询语句，只需额外实现`RepositoryEnhancer`接口即可。
{% endhint %}

## 业务逻辑层（Service）

{% code title="FooService.java" %}

```java
package com.example.demo.service;

import com.example.*;
import com.taocares.commons.beans.BeanUtils;
import com.taocares.commons.jpa.SpecificationFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.*;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class FooService {

    @Autowired
    private FooRepository fooRepository;

    public Page<FooDto> findAll(FooQo fooQo, Pageable pageable) {
        Specification<Foo> specification = SpecificationFactory.getSpecification(fooQo);
        Page<Foo> page = fooRepository.findAll(specification, pageable);
        List<FooDto> dtoList = BeanUtils.copyProperties(page.getContent(), FooDto.class);
        return new PageImpl<>(dtoList, pageable, page.getTotalElements());
    }
}
```

{% endcode %}

{% hint style="info" %}
进行业务逻辑操作
{% endhint %}

## 请求控制层（Controller）

{% code title="FooController.java" %}

```java
package com.example.demo.controller;

import com.example.demo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.*;

@RestController
@RequestMapping("/foos")
@Slf4j
@Api(tags = "Foo CRUD服务")
public class FooController {

    @Autowired
    private FooService fooService;

    @GetMapping("/")
    @ApiOperation("根据条件分页查询结果")
    public Page<FooDto> findAll(FooQo fooQo, Pageable pageable) {
        log.debug("Query Object: {}; pageable: {}", fooQo, pageable);
        return fooService.findAll(fooQo, pageable);
    }
}
```

{% endcode %}

{% hint style="info" %}
映射HTTP请求，使用Swagger定义接口
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://taocares.gitbook.io/development-guide/kai-fa-zhi-nan/jian-dan-shi-li.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
