SpringBoot+JPA @Autowired注入泛型成员 封装统一接口

SpringBoot

输入java -version得到我的java version "16.0.1"
cd到pom.xml文件所在位置即项目根目录并执行指令./mvnw dependency:list来查看引用版本:

  • org.springframework.data:spring-data-jpa:2.5.2
  • javax.validation:validation-api:2.0.1.Final
  • com.alibaba:fastjson:1.2.78
  • org.projectlombok:lombok:1.18.20
  • org.springframework:spring-web:5.3.8
  • org.springframework.boot:spring-boot:2.5.2

实体类

Media.java

一个很普通的实体类,包名省略。

package com.example.demo.entity;

import com.alibaba.fastjson.annotation.JSONField;
import java.io.Serializable;
import lombok.*;

import javax.persistence.*;

@SuppressWarnings({
    
    "LombokEqualsAndHashCodeInspection"})
@EqualsAndHashCode
@ToString
@Getter
@Setter
@Entity
@Table(name = "media")
@AllArgsConstructor
@NoArgsConstructor
public class Media implements Serializable
{
    
    
	@Id
	@JSONField(ordinal = 1)
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id", insertable = false, updatable = false)
	private Integer id;
	@JSONField(ordinal = 2)
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "book_id", updatable = false)
	private Integer bookId;
	@JSONField(ordinal = 3)
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "url", length = 128)
	private String url;
}

持久层

IMediaRepository.java

一个啥也没有的接口。

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import com.example.demo.entity.Media;

public interface IMediaRepository extends
	JpaRepository<Media, Integer>,
	JpaSpecificationExecutor<Media>
{
    
    
}

服务

写一些接口。

IService.java

package com.example.demo.service;

import org.springframework.lang.Nullable;

public interface IService<T, K>
{
    
    
	@Nullable
	T get(K primaryKey);
	
	@Nullable
	T addOrUpdate(T obj);
	
	boolean delete(K primaryKey);
}

IQueryService.java

package com.example.demo.service;

import java.util.*;

public interface IQueryService<T>
{
    
    
	List<T> find(int index, int size);
	
	long count();
	
	List<T> find(int index, int size, Map<String, String> colAndPatterns);
	
	long count(Map<String, String> colAndPatterns);
}

BaseService.java

抽象服务类。

可以这样写

package com.example.demo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.*;
import com.example.demo.util.Common;

import javax.persistence.criteria.*;
import javax.validation.constraints.*;
import java.util.*;

public abstract class BaseService<T, K, R extends JpaRepository<T, K> & JpaSpecificationExecutor<T>>
	implements IService<T, K>, IQueryService<T>
{
    
    
	@Autowired
	protected R repo; // 让@Autowired自己找合适的类注入 
	
	...
	
	@SuppressWarnings({
    
    "UnnecessarySemicolon", "OverlyBroadCatchBlock"})
	@Override
	public final T addOrUpdate(@NotNull final T obj)
	{
    
    
		T ret = null;
		if (canAddOrUpdate(obj))
		{
    
    
			try
			{
    
    
				ret = repo.saveAndFlush(obj);
			}
			catch (Exception e)
			{
    
    
				e.printStackTrace();
			}
		}
		return ret;
	}
	
	protected abstract boolean canAddOrUpdate(final T obj);
}

还可以这样写

感觉这个比上面那种要好一点,减少一个泛型参数。

package com.example.demo.service;

public abstract class BaseService<T, K> implements IService<T, K>, IQueryService<T>
{
    
    
	@Autowired
	protected JpaRepository<T, K> repo;
	@Autowired
	protected JpaSpecificationExecutor<T> queryRepo; // 少一个泛型参数,多注入一次

	...

	@SuppressWarnings({
    
    "UnnecessarySemicolon", "OverlyBroadCatchBlock"})
	@Override
	public final T addOrUpdate(@NotNull final T obj)
	{
    
    
		T ret = null;
		if (canAddOrUpdate(obj))
		{
    
    
			try
			{
    
    
				ret = repo.saveAndFlush(obj);
			}
			catch (Exception e)
			{
    
    
				e.printStackTrace();
			}
			finally
			{
    
    
				;
			}
		}
		return ret;
	}
	
	protected abstract boolean canAddOrUpdate(final T obj);
}

MediaService.java

服务类指定了类参数,然后实现之前的BaseService的抽象方法。

package com.example.demo.service;

import org.springframework.stereotype.Service;
import com.example.demo.entity.Media;
import com.example.demo.repository.IMediaRepository;

@Service(value = "mediaService")
public class MediaService extends BaseService<Media, Integer, IMediaRepository>
{
    
    
}


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

import org.springframework.stereotype.Service;
import com.example.demo.entity.Media;

@Service(value = "mediaService")
public class MediaService extends BaseService<Media, Integer>
{
    
    
	...
}

控制器

IController.java

接口

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

public interface IController<T, K>
{
    
    
	@RequestMapping(method = RequestMethod.POST)
	String add(T body);
	
	@RequestMapping(method = RequestMethod.PUT)
	String update(T body);
	
	@RequestMapping(method = RequestMethod.DELETE)
	String delete(K id);
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	String gets(Integer index, Integer size);
	
	@RequestMapping(method = RequestMethod.GET)
	String get(K id);
}

BaseController.java

package com.example.demo.controller;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.demo.service.BaseService;

@RestController
public abstract class BaseController<T, K> implements IController<T, K>
{
    
    
	@Autowired
	protected BaseService<T, K> service;
	
	@Override
	public String add(@RequestBody final T body)
	{
    
    
		return JSON.toJSONString(service.addOrUpdate(body));
	}
	
	...

}

MediaController.java

方法头顶上的注解也是可以继承的,但是参数注解重写方法就得重新再加一遍,忽略这一点造成的bug很低级。

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.entity.Media;

@RestController
@RequestMapping("/media")
public class MediaController extends BaseController<Media, Integer>
{
    
    
}

测试接口

欸呦图丢了跑通。

猜你喜欢

转载自blog.csdn.net/dscn15848078969/article/details/120627984
今日推荐