SpringDataJPA之Base抽象类+范型快速实现增删查改


基本配置

pom.xml

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://xxx:3306/mall?serverTimezone=GMT%2b8
username: xxxx
password: xxxx
jpa:
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true

  • 数据库基本配置
  • 自动更新数据库表
  • 使用驼峰命名方式
  • 显示sql

实体类

BaseEntity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Getter
@Setter
@DynamicUpdate
@DynamicInsert
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;

@CreatedDate
@Column(updatable = false)
private Long createTime;

@LastModifiedDate
@Column
private Long updateTime;

@CreatedBy
@Column(name = "created_by", updatable = false, length = 64)
private String createdBy;

@LastModifiedBy
@Column(name = "updated_by", length = 64)
private String updatedBy;

@Column(columnDefinition = "tinyint(1) default 0")
private Boolean deleted=false;

}

用法

1
2
3
4
5
6
7
8
@Getter
@Setter
@Entity
@Table(name = "user_info")
@Where(clause = "deleted<>1")
public class User extends BaseEntity {
...
}

数据访问层

BaseRepository.java

1
2
public interface BaseRepository<Entity extends BaseEntity> extends JpaRepository<Entity,Long>, JpaSpecificationExecutor<Entity> {
}

用法

1
2
3
4
@Repository
public interface UserRepository extends BaseRepository<User> {
...
}

服务层

BaseService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public abstract class BaseService<Entity extends BaseEntity>{
private final BaseRepository<Entity> repository;

protected BaseService(BaseRepository<Entity> repository) {
this.repository = repository;
}

public CommonResult save(Entity entity) {
return CommonResult.success(repository.save(entity));
}
public CommonResult saveAll(List<Entity> entities) {
if (((boolean) FieldUtil.getFieldValueByName("deleted", entities.get(0)))) {
repository.deleteAll(entities);
return CommonResult.success("删除成功");
}
return CommonResult.success(repository.saveAll(entities));
}
public CommonResult list() {
return CommonResult.success(repository.findAll());
}
public CommonResult page(int pageNumber, int pageSize, Entity entity) {
return CommonResult.success(repository.findAll((Specification<Entity>) (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicateList = new ArrayList<>();
List<Map<String,Object>> fieldList = FieldUtil.getFiledsInfo(entity);
fieldList.stream().filter(field-> field.get("value")!=null ).forEach(field->{
String name = field.get("name").toString();
Object value = field.get("value");
Class<?> type = (Class<?>) field.get("type");
if (!Collection.class.isAssignableFrom(type) && !type.cast(value).toString().isEmpty()) {
if (String.class.isAssignableFrom(type)) {
predicateList.add(criteriaBuilder.like(root.get(name), "%" + value + "%"));
}else {
predicateList.add(criteriaBuilder.equal(root.get(name),type.cast(value)));
}
}

});
return criteriaQuery.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction();
}, PageRequest.of(pageNumber - 1, pageSize)));
}


}

FieldUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class FieldUtil {
public static final Logger log = LoggerFactory.getLogger(FieldUtil.class);

/**
* 根据属性名获取属性值
*/
public static Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[]{});
Object value = method.invoke(o, new Object[]{});
return value;
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}

/**
* 获取属性名数组
*/
public static String[] getFiledName(Object o) {
Field[] fields = o.getClass().getDeclaredFields();
String[] fieldNames = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getType());
fieldNames[i] = fields[i].getName();
}
return fieldNames;
}

/**
* 获取属性类型(type),属性名(name),属性值(value)的map组成的list
*/
public static List<Map<String,Object>> getFiledsInfo(Object o) {
Field[] fields1 = o.getClass().getDeclaredFields();
Field[] fields2 = o.getClass().getSuperclass().getDeclaredFields();
Field[] fields = new Field[fields1.length + fields2.length];
fields = ArrayUtil.append(fields1, fields2);
String[] fieldNames = new String[fields.length];
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> infoMap = null;
for (Field field : fields) {
infoMap = new HashMap<>();
infoMap.put("type", field.getType());
infoMap.put("name", field.getName());
infoMap.put("value", getFieldValueByName(field.getName(), o));
list.add(infoMap);
}
return list;
}

/**
* 获取对象的所有属性值,返回一个对象数组
*/
public static Object[] getFiledValues(Object o) {
String[] fieldNames = getFiledName(o);
Object[] value = new Object[fieldNames.length];
for (int i = 0; i < fieldNames.length; i++) {
value[i] = getFieldValueByName(fieldNames[i], o);
}
return value;
}
}

用法

1
2
3
4
5
6
7
8
9
@Service
public class UserService extends BaseService<User>{

protected UserService(UserRepository repository) {
super(repository);
}
...
}

Web服务层

BaseController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class BaseController<Entity extends BaseEntity> {
private final BaseService<Entity> service;
private final Class<?> clazz;

public BaseController(BaseService<Entity> service, Class<?> clazz) {
this.service = service;
this.clazz = clazz;
}
@GetMapping("page")
public CommonResult page(int pageNumber, int pageSize, String contain,Entity entity) {
return service.page(pageNumber, pageSize, entity) ;
}
@GetMapping("list")
public CommonResult list() {
return service.list();
}
@PostMapping("saveAll")
public CommonResult saveAll(String data) {
return service.saveAll(JSONUtil.toList(JSONUtil.parseArray(data), (Class<Entity>) clazz));
}
}

用法

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequestMapping("/user")
public class UserController extends BaseController<User>{
@Autowired
UserService userService;

public UserController(UserService service) {
super(service, User.class);
}
...
}

扩展:树形数据

TreeEntity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class TreeEntity<T> extends BaseEntity{

private int sort;
@Column(columnDefinition = "boolean default false")
private Boolean hidden;
@ManyToOne
@JsonIgnoreProperties("children")
private T parent;

@OneToMany(mappedBy = "parent")
@OrderBy("sort asc")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Set<T> children;
}

TreeService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public abstract class TreeService<Entity extends TreeEntity<Entity>>
extends BaseService<Entity> {

private final BaseRepository<Entity> repository;
protected TreeService(BaseRepository<Entity> repository) {
super(repository);
this.repository = repository;
}

@Override
public CommonResult saveAll(List<Entity> entities) {
entities.forEach(entity -> {
if (entity.getDeleted()) {
deleteChildren(entity);
}
});
return super.saveAll(entities);
}
private void deleteChildren(Entity entity) {
if (entity == null) {
return;
}
entity.setDeleted(true);
if (entity.getChildren() == null) {
return;
}
entity.getChildren().forEach(this::deleteChildren);
}

public CommonResult listTree() {
Specification<Entity> specification = (root, criteriaQuery, criteriaBuilder) -> {
criteriaQuery.where(
criteriaBuilder.isNull(root.get("parent"))
);
criteriaQuery.orderBy(criteriaBuilder.asc(root.get("sort")));
return criteriaQuery.getRestriction();
};
List<Entity> list = repository.findAll(specification);
return CommonResult.success(list);
}


}

TreeController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TreeController<Entity extends TreeEntity<Entity>>
extends BaseController<Entity>{

private final TreeService<Entity> service;
public TreeController(TreeService<Entity> service, Class<?> clazz) {
super(service, clazz);
this.service = service;
}
@Override
@GetMapping("list")
public CommonResult list() {
return service.listTree();
}
}

← Prev RabbitMQ通过TTL和DLX实现延时队列(动态定时任务) | Nginx服务器SSL证书安装部署 && HTTP自动跳转HTTPS Next →