SpringBoot开发案例之整合Spring-data-jpa进阶篇

前言

有人说 从 jdbc->jdbctemplate->hibernation/mybatis 再到 jpa,真当开发人员的学习时间不要钱?我觉得到 h/m 这一级的封装已经有点过了,再往深处走就有病了。

还有人说JPA 很反人类(一个面试官),还举了一个很简单举了例子说:一个数据库如果有 50 个字段,那你写各种条件查询不是要写很多?就是应该用类似 SQL 的方式来查询啊?

其实在我看来,存在即合理,人们总是向着好的方向去发展,学习什么不需要成本,底层语言牛逼倒是去学啊,不还是看不懂,弄不明白。很多知识对于程序员来说,都是一通百通,查询文档就是了,最主要的是能方便以后的开发即可。

对于反人类这一说,只能说 to young to simple,JPA的初衷肯定也不会是让你写一个几十个字段的查询,顶多一到两个而已,非要这么极端?再说JPA也是提供了EntityManager来实现SQL或者HQL语句查询的不是,JPA本质上还是集成了Hibernate的很多优点的。

进阶查询

需求:

学生表(app_student)、班级表(app_class)、当然表结构比较简单,比如这时候我们需要查询学生列表,但是需要同时查询班级表的一些数据,并以JSON或者实体的方式返回给调用者。

本次需求,主要实现JPA的以下几个特性:

  • 封装EntityManager基类
  • 多表查询返回一个List
  • 多表查询返回一个Map
  • 多表查询返回一个实体

Entitymanager的核心概念图:

1190778-20171004143209911-1516587547.jpg

实现

班级表:

@Entity
@Table(name = "app_class")
public class AppClass {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", nullable = false)
	private Integer id;
	private String className;
	private String teacherName;
	//忽略部分代码
}

学生表:

@Entity
@Table(name = "app_student")
public class AppStudent {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", nullable = false)
	private Integer id;
	private Integer classId;
	private String name;
	private Integer age;
	//忽略部分代码
}

封装接口 DynamicQuery:

/**
 * 扩展SpringDataJpa, 支持动态jpql/nativesql查询并支持分页查询
 * 使用方法:注入ServiceImpl
 * 创建者 张志朋
 * 创建时间	2018年3月8日
 */
public interface DynamicQuery {

	public void save(Object entity);

	public void update(Object entity);

	public <T> void delete(Class<T> entityClass, Object entityid);

	public <T> void delete(Class<T> entityClass, Object[] entityids);
	
	 /**
     * 查询对象列表,返回List
     * @param resultClass
     * @param nativeSql
     * @param params
     * @return  List<T>
     * @Date	2018年3月15日
     * 更新日志
     * 2018年3月15日  张志朋  首次创建
     *
     */
	<T> List<T> nativeQueryList(String nativeSql, Object... params);
	
	 /**
     * 查询对象列表,返回List<Map<key,value>>
     * @param nativeSql
     * @param params
     * @return  List<T>
     * @Date	2018年3月15日
     * 更新日志
     * 2018年3月15日  张志朋  首次创建
     *
     */
	<T> List<T> nativeQueryListMap(String nativeSql,Object... params);

	 /**
     * 查询对象列表,返回List<组合对象>
     * @param resultClass
     * @param nativeSql
     * @param params
     * @return  List<T>
     * @Date	2018年3月15日
     * 更新日志
     * 2018年3月15日  张志朋  首次创建
     *
     */
	<T> List<T> nativeQueryListModel(Class<T> resultClass, String nativeSql, Object... params);

}

封装实现 DynamicQueryImpl:

/**
 * 动态jpql/nativesql查询的实现类
 * 创建者 张志朋
 * 创建时间	2018年3月8日
 */
@Repository
public class DynamicQueryImpl implements DynamicQuery {

	Logger logger = LoggerFactory.getLogger(DynamicQueryImpl.class);

	@PersistenceContext
	private EntityManager em;

	public EntityManager getEntityManager() {
		return em;
	}

	@Override
	public void save(Object entity) {
		em.persist(entity);
	}

	@Override
	public void update(Object entity) {
		em.merge(entity);
	}

	@Override
	public <T> void delete(Class<T> entityClass, Object entityid) {
		delete(entityClass, new Object[] { entityid });
	}

	@Override
	public <T> void delete(Class<T> entityClass, Object[] entityids) {
		for (Object id : entityids) {
			em.remove(em.getReference(entityClass, id));
		}
	}
	private Query createNativeQuery(String sql, Object... params) {
		Query q = em.createNativeQuery(sql);
		if (params != null && params.length > 0) {
			for (int i = 0; i < params.length; i++) {
				q.setParameter(i + 1, params[i]); // 与Hiberante不同,jpa
													// query从位置1开始
			}
		}
		return q;
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> nativeQueryList(String nativeSql, Object... params) {
		Query q = createNativeQuery(nativeSql, params);
		q.unwrap(SQLQuery.class).setResultTransformer(Transformers.TO_LIST);
		return q.getResultList();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> nativeQueryListModel(Class<T> resultClass,
			String nativeSql, Object... params) {
		Query q = createNativeQuery(nativeSql, params);;
		q.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(resultClass));
		return q.getResultList();
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> nativeQueryListMap(String nativeSql, Object... params) {
		Query q = createNativeQuery(nativeSql, params);
		q.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		return q.getResultList();
	}

}

业务 IStudentService:

public interface IStudentService {
	 /**
	  * 返回List<Object[]>
	  * @Author  科帮网
	  * @return  List<Object[]>
	  * @Date	2018年3月28日
	  * 更新日志
	  * 2018年3月28日  科帮网 首次创建
	  *
	  */
	 List<Object[]> listStudent();
	 /**
	  * 返回List<Student>
	  * @Author  科帮网
	  * @return  List<Student>
	  * @Date	2018年3月28日
	  * 更新日志
	  * 2018年3月28日  科帮网 首次创建
	  *
	  */
     List<Student> listStudentModel();
     /**
      * List<Map<Object, Object>>
      * @Author  科帮网
      * @return  List<Map<Object,Object>>
      * @Date	2018年3月28日
      * 更新日志
      * 2018年3月28日  科帮网 首次创建
      *
      */
     List<Map<Object, Object>> listStudentMap();
}

业务实现 StudentServiceImpl:

@Service
public class StudentServiceImpl implements IStudentService {

	@Autowired
	private DynamicQuery dynamicQuery;
	
	
	@Override
	public List<Object[]> listStudent() {
		String nativeSql = "SELECT s.id AS studentId,c.id AS classId,c.class_name AS className,c.teacher_name AS teacherName,s.name,s.age FROM app_student s,app_class c";
		List<Object[]> list = dynamicQuery.nativeQueryList(nativeSql, new Object[]{});
		return list;
	}
	
	@Override
	public List<Student> listStudentModel() {
		String nativeSql = "SELECT s.id AS studentId,c.id AS classId,c.class_name AS className,c.teacher_name AS teacherName,s.name,s.age FROM app_student s,app_class c";
		List<Student> list = dynamicQuery.nativeQueryListModel(Student.class, nativeSql, new Object[]{});
		return list;
	}

	@Override
	public List<Map<Object,Object>> listStudentMap() {
		String nativeSql = "SELECT s.id AS studentId,c.id AS classId,c.class_name AS className,c.teacher_name AS teacherName,s.name,s.age FROM app_student s,app_class c";
		List<Map<Object,Object>> list = dynamicQuery.nativeQueryListMap(nativeSql, new Object[]{});
		return list;
	}

}

接口测试:

@Api(tags ="测试接口")
@RestController
@RequestMapping("/test")
public class StudentController {
	private final static Logger LOGGER = LoggerFactory.getLogger(StudentController.class);
	
	@Autowired
	private IStudentService studentService;
	
	@ApiOperation(value="学生List")
	@PostMapping("/list")
	public Result list(HttpServletRequest request){
		LOGGER.info("学生List");
		List<Object[]> list = studentService.listStudent();
		return Result.ok(list);
	}
	@ApiOperation(value="学生Map")
	@PostMapping("/listMap")
	public Result listMap(HttpServletRequest request){
		LOGGER.info("学生Map");
		List<Map<Object, Object>> list = studentService.listStudentMap();
		return Result.ok(list);
	}
	@ApiOperation(value="学生Model")
	@PostMapping("/listModel")
	public Result listModel(HttpServletRequest request){
		LOGGER.info("学生Model");
		List<Student> list = studentService.listStudentModel();
		return Result.ok(list);
	}
}

Swagger2测试

1.png

返回List< Object[] >:

2.png

返回List< Map< Object, Object > >:

3.png

返回List< Student >:

4.png

源码:https://gitee.com/52itstyle/spring-data-jpa

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android知识点总结

Java总结IO之总集篇

字符流和字节流向来各行其事,很少有交集。 但Reader和Writer有两个奇子,名叫InputStreamReader(男)和OutputStreamWri...

1365
来自专栏mukekeheart的iOS之旅

No.009 Palindrome Number

9. Palindrome Number Total Accepted: 136330 Total Submissions: 418995 Difficulty...

2287
来自专栏IT笔记

SpringBoot开发案例之整合Spring-data-jpa进阶篇

前言 有人说 从 jdbc->jdbctemplate->hibernation/mybatis 再到 jpa,真当开发人员的学习时间不要钱?我觉得到 h/m ...

3217
来自专栏小樱的经验随笔

POJ 2492 A Bug's Life

A Bug's Life Time Limit: 10000MS Memory Limit: 65536K Total Submissions:...

28910
来自专栏函数式编程语言及工具

FunDA(1)- Query Result Row:强类型Query结果行

    FunDA的特点之一是以数据流方式提供逐行数据操作支持。这项功能解决了FRM如Slick数据操作以SQL批次模式为主所产生的问题。为了实现安全高效的数据...

2029
来自专栏数据结构与算法

HDU 5536 Chip Factory

Problem Description John is a manager of a CPU chip factory, the factory produc...

35615
来自专栏函数式编程语言及工具

SDP(3):ScalikeJDBC- JDBC-Engine:Fetching

  ScalikeJDBC在覆盖JDBC基本功能上是比较完整的,而且实现这些功能的方式比较简洁,运算效率方面自然会稍高一筹了。理论上用ScalikeJDBC作为...

3805
来自专栏我是攻城师

Fastjson解析嵌套Map例子

3995
来自专栏码匠的流水账

聊聊storm的reportError

storm-2.0.0/storm-client/src/jvm/org/apache/storm/task/IErrorReporter.java

1473
来自专栏ml

hdu----(1075)What Are You Talking About(trie之查找)

What Are You Talking About Time Limit: 10000/5000 MS (Java/Others)    Memory Lim...

36911

扫码关注云+社区

领取腾讯云代金券