按照三层架构+damin实现基本功能
1.写好实体类后,要加BaseEntity接口。
2.加@data后可以不写get,set方法。
3.@Entity是实体类的注释。
4.对于json数据,依旧为string类型,但是数据库改为text类型即可。
1.写好实体类后,利用jpa自动建表,为上图的none-->改为update;
这个人写的很好,从理解方面无可挑剔。
1. Controller/Service/DAO简介:
Controller是管理业务(Service)调度和管理跳转的。
Service是管理具体的功能的。
Controller只负责管理,而Service负责实施。
DAO只完成增删改查,虽然可以1-n,n-n,1-1关联,模糊、动态、子查询都可以。但是无论多么复杂的查询,dao只是封装增删改查。至于增删查改如何去实现一个功能,dao是不管的。
总结这三者,通过例子来解释:
Controller像是服务员,顾客点什么菜,菜上给几号桌,都是ta的职责;
Service是厨师,action送来的菜单上的菜全是ta做的;
Dao是厨房的小工,和原材料打交道的事情全是ta管。
相互关系是,小工(dao)的工作是要满足厨师(service)的要求,厨师要满足服务员(controller)转达的客户(view)的要求,服务员自然就是为客户服务喽。
现在最基本的分层方式,结合了SSH架构。Entity层就是对应的数据库表的实体类。Dao层是使用了Hibernate连接数据库、操作数据库(增删改查)。Service层:引用对应的Dao数据库操作。Controller层:引用对应的Service层,结合SpringMVC注释,跳转到指定的页面,当然也能接受页面传递的请求数据,也可以做些计算处理。
以上的Hibernate, SpringMVC,都需要注入到Spring的配置文件中,Spring把这些联系起来,成为一个整体。
2. 三大框架SpringMVC/Hibernate/Spring
简单地说:
SpringMVC——控制用的;
Hibernate——操作数据库的;
Spring——解耦用的。
详细地说:
SpringMVC在SSH框架中起控制的作用,其核心是Controller,主要控制逻辑关系的处理。
Hibernate是数据持久化层,是一种新的对象、关系的映射工具,提供了从Java类到数据表的映射,也提供了数据查询和恢复等机制,大大减少数据访问的复杂度。把对数据库的直接操作,转换为对持久对象的操作。
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。面向接口的编程,由容器控制程序之间的依赖关系,而非传统实现中,由程序代码直接操控。这就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。依赖注入,即组件之间的依赖关系由容器在运行期决定,形象地说,即由容器动态地将某种依赖关系注入到组件之中,起到的主要作用是解耦。
SpringMVC、Spring、Hibernate在各层的作用:
(1)SpringMVC负责Web层:接收网页中表单提交的数据,然后通过Controller进行处理,再跳转到对应的网页。在springmvc-servlet.xml中定义<servlet-mapping>,Controller会加载。
(2) Spring负责业务层管理,即Service(或Manager)。
Service为action提供统计的调用接口,封装持久层的DAO;
可以写一些自己的业务方法;
统一的Javabean管理方法;
声明式事务管理;
集成Hibernate。
(3)Hibernate,负责持久化层,完成对数据库的crud操作。提供OR/Mapping。它由一组.hbm.xml文件和POJO(或者带有注释的POJO),是跟数据库中的表相对应的。然后定义DAO,这些是跟数据库打交道的类,它们会使用PO。
3. 框架业务逻辑分析:
在SpringMVC + Spring + Hibernate的系统中,
对象的调用流程是:JSP—Controller—Service—DAO—Hibernate。
数据的流向是:Controller接受用户的数据,封装成VO或PO,再调用业务层的Bean类,完成各种业务处理后再Forward。而业务层Bean收到这个PO对象之后,会调用DAO接口方法,进行持久化操作。
SSH框架的优点:
Hibernate的最大好处就是根据数据库的表,反向生成实体类,并且还有关系在里面,还有就是它对数据的操作也很方便;
Spring,省去了在类里面new对象的过程,把这个调用与被调用的关系直接展示到了配置文件里,做任何操作都变得简单了。
简单流程举例说明:
程序框架搭建好,并且把各种jar包导入后,就开始进行业务逻辑分析——
Controller(控制逻辑)层:它是负责在页面和程序之间传输数据的,还有作用是做页面跳转。页面由用户填写表单数据,点击提交按钮,页面的表单数据由传入Service层。
Service层(业务逻辑层):负责的是对数据的处理。如果没有数据处理任务的话,此层只做单纯的数据传递作用,而后又到了DAO层。
DAO层(数据库操作层):负责对数据向数据库增删改查的操作。
在该注册的框架中,如果不使用Spring的话,每个层之间的数据传递都需要new一个调用该层数据的类的实例。而使用了Spring的话,需要做的就是把DAO层和BIZ层的每个类都写一个接口类,接口类里写实现类的方法,在调用的时候不new对象,直接用对象点(.)方法就可以,别忘了对每个对象加上set/get方法。
三层架构dao、service、controller
三层架构写法 按步骤来无敌写法,搞两个。
这个还加了前端页面
bean实体类:
package com.spring.comtroller.demo.bean;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name="user", schema = "myapp")
public class Student implements Serializable{
@Id
@GeneratedValue
@Column(name="id")
private long id;
@Column(name = "name")
private String name;
public Student() {
}
public Student(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
controller控制类:
package com.spring.comtroller.demo.controller;
import com.spring.comtroller.demo.bean.Student;
import com.spring.comtroller.demo.result.ResultModel;
import com.spring.comtroller.demo.result.ResultModelTool;
import com.spring.comtroller.demo.service.IStudent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping(value = "/students")
public class StudentController {
@Autowired
IStudent studentService;
@RequestMapping(value = "/all",method = RequestMethod.GET)
public ResultModel getAllStudent(){
List<Student> studentList = studentService.getAllStudent();
Map<String,List<Student>> studentMap = new HashMap<>();
if (studentList!=null){
studentMap.put("students",studentList);
}
ResultModel resultModel = new ResultModel();
resultModel.setCode(0);
resultModel.setData(studentMap);
return ResultModelTool.handleResultModel(resultModel);
}
@PostMapping(value = "/addStudent")
public ResultModel addStudent(@RequestParam long id,@RequestParam String name){
Student student = new Student(id,name);
int errorCode = studentService.addStudent(student);
ResultModel resultModel = new ResultModel();
resultModel.setCode(errorCode);
resultModel.setData(student);
return ResultModelTool.handleResultModel(resultModel);
}
@PostMapping(value = "/updateStudent")
public ResultModel updateStudent(@RequestParam long id,@RequestParam String name){
Student student = new Student(id,name);
int errorCode = studentService.updateStudent(student);
ResultModel resultModel = new ResultModel();
resultModel.setCode(errorCode);
resultModel.setData(student);
return ResultModelTool.handleResultModel(resultModel);
}
@GetMapping(value = "/deleteStudent/{id}")
public ResultModel deleteStudent(@PathVariable long id){
int errorCode = studentService.deleteStudent(id);
ResultModel resultModel = new ResultModel();
resultModel.setCode(errorCode);
List<Student> studentList = studentService.getAllStudent();
Map<String,List<Student>> studentMap = new HashMap<>();
if (studentList!=null){
studentMap.put("students",studentList);
}
resultModel.setData(studentMap);
return ResultModelTool.handleResultModel(resultModel);
}
}
respository层:
public interface JpaStudentRepository extends JpaRepository<Student,Long>{
}
public interface StudentRepository extends Repository<Student,Long> {
}
service层:
public interface IStudent {
//获取所有的学生
List<Student> getAllStudent();
//增
int addStudent(Student student);
//删
int deleteStudent(long id);
//改
int updateStudent(Student student);
//查
Student queryStudent(long id);
}
service实现类:
package com.spring.comtroller.demo.service;
import com.spring.comtroller.demo.bean.Student;
import com.spring.comtroller.demo.repository.JpaStudentRepository;
import com.spring.comtroller.demo.result.ErrorCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentImpl implements IStudent {
@Autowired
JpaStudentRepository jpaStudentRepository;
@Override
public List<Student> getAllStudent() {
List<Student> students = jpaStudentRepository.findAll();
System.out.println(students.toString());
return students;
}
@Override
public int addStudent(Student student) {
if (jpaStudentRepository.existsById(student.getId())){
System.out.println("user is existed");
return ErrorCode.EXISTUSER;
}
Student saveStudent = jpaStudentRepository.save(student);
if (saveStudent != null && saveStudent.getId() == student.getId()) {
System.out.println("save success");
return ErrorCode.ADDSUCCESS;
} else {
System.out.println("save failure");
return ErrorCode.ADDFAIL;
}
}
@Override
public int deleteStudent(long id) {
if (jpaStudentRepository.existsById(id)) {
jpaStudentRepository.deleteById(id);
System.out.println("删除成功");
return ErrorCode.DELETESUCCESS;
}
System.out.println("删除失败");
return ErrorCode.NOTEXISTUSER;
}
@Override
public int updateStudent(Student student) {
if (jpaStudentRepository.existsById(student.getId())){
jpaStudentRepository.save(student);
System.out.println("更新成功");
return ErrorCode.UPDATESUCCESS;
}
System.out.println("更新失败");
return ErrorCode.UPDATEFAIL;
}
@Override
public Student queryStudent(long id) {
Student student = null;
if (jpaStudentRepository.existsById(id)){
student = jpaStudentRepository.findById(id).get();
System.out.println(student.toString());
}
return student;
}
}
选择部分字段进行返回 Spring Data JPA 进阶(自定义查询,原生 SQL 查询)
自定义查询语句(JPQL)
使用@Query 自定义查询
// 根据学生姓名查询学生记录 Student是实体类的名称
@Query("select s from Student s where s.name=?1")
List<Student> getStudentName(String name);
1
2
3
在controller中调用
/**
* 根据学生姓名查询学生记录 http://localhost:8080/getStuName?name=张三
*
* @param student * @return
*/
@RequestMapping("/getStuName")
public Object getStudentName(String name) {
List<Student> student=repository.getStudentName(name);
return student;
}
@Query 与 @Modifying 的联合使用
@Transactional 开启事务
@Modifying 识别执行更新操作
@Query() SQL语句
三个主注解缺一不可
// 通过学生id修改学生姓名 三个主注解缺一不可
@Transactional//开启事务
@Modifying//识别执行更新操作
@Query("update Student s set s.name=?1 where s.id=?2")
int updateStuById(String name, int id);
controller调用
/**
* 通过学生id修改学生姓名 http://localhost:8080/updateStuById?name=张3&id=1
*
* @param student * @return
*/
@RequestMapping("/updateStuById")
public Object updateStuById(String name,int id) {
int student=repository.updateStuById(name,id);
return student;
}
索引参数与命名参数
索引参数如下例代码所示,索引值从 1 开始,查询中 ”?X” 个数需要与方法定义的参数个数相一致,并且顺序也要一致:
@Transactional
@Modifying
@Query("update Student s set s.studentName=?1 where s.studentId=?2")
int setFixedStudentNameFor(String studentName,int studentId);
2)命名参数(推荐使用这种方式) 可以定义好参数名,赋值时采用@Param(“参数名”),而不用管顺序。
3) 在 StudentRepository 里添加如下代码,实现姓名的模糊查询:
@Query("select s from Student s where s.studentName like %:studentName% ")
List<Student> queryByname(@Param(value = "studentName") String studentName);
在 controller 里面进行调用,代码如下:
/***
* http://localhost:8080/queryByname?name=刘
* @param name * @return
*/
@RequestMapping("/queryByname")
public Object queryByname(String name) {
List<Student> student = repository.queryByname(name);
return student;
}
原生 SQL 查询
nativeQuery=true 开启原生SQL
//利用原生的 SQL 进行查询操作
@Query(value = "select s.* from studenttb s where s.student_name=?1", nativeQuery = true)
public List<Student> findStudentByName(String name);
//利用原生的 SQL 进行删除操作
@Query(value = "delete from studenttb where student_id=?1 ", nativeQuery = true)
@Modifying
@Transactional
public int deleteStudentById(int uid);
//利用原生的 SQL 进行修改操作
@Query(value = "update studenttb set student_name=?1 where student_id=?2 ", nativeQuery = true)
@Modifying
@Transactional
public int updateStudentName(String name,int id);
//利用原生的 SQL 进行插入操作
@Query(value = "insert into studenttb(student_name,student_age) value(?1,?2)", nativeQuery = true)
@Modifying
@Transactional
public int insertStudent(String name,int age);
//利用原生的 SQL 实现姓名的模糊查询
@Query(value=" SELECT * FROM studenttb WHERE STUDENT_NAME LIKE %:name% ",nativeQuery=true)
List<Student> queryBynameSQL(@Param(value = "name") String name);
controller调用
//原生 sql 的调用
/***
*查询学生
* http://localhost:8080/findStudentByName?name=刘一
* @param name * @return
*/
@RequestMapping("/findStudentByName")
public Object findStuByName(String name) {
List<Student> student = repository.findStudentByName(name);
return student;
}
/***
*删除学生
* http://localhost:8080/deleteStudentById?id=刘
* @param name * @return
*/
@RequestMapping("/deleteStudentById")
public Object deleteStudentById(int id) {
int i = repository.deleteStudentById(id);
Map<String,Object> map=new HashMap<String,Object>();
if(i>0) {
map.put("success", true);
}else {
map.put("success", false);
}
return map;
}
/***
* 修改学生名字
*http://localhost:8080/updateStudentName?name=Tom&id=1
* @param name * @return
*/
@RequestMapping("/updateStudentName")
public Object updateStudentName(String name,int id) {
int i = repository.updateStudentName(name,id);
Map<String,Object> map=new HashMap<String,Object>();
if(i>0) {
map.put("success", true);
}else {
map.put("success", false);
}
return map;
}
/***
*添加学生信息
* http://localhost:8080/insertStudent?name=xiao&age=18
129
* @param name * @return
*/
@RequestMapping("/insertStudent")
public Object insertStudent(String name,int age) {
int i = repository.insertStudent(name,age);
Map<String,Object> map=new HashMap<String,Object>();
if(i>0) {
map.put("success", true);
}else {
map.put("success", false);
}
return map;
}
/***
* 模糊查询
* http://localhost:8080/queryBynameSQL?name=刘
* @param name * @return
*/
@RequestMapping("/queryBynameSQL")
public Object queryBynameSQL(String name) {
List<Student> student= repository.queryBynameSQL(name);
return student;
}
JAP 动态 SQL 查询
JpaSpecificationExecutor 接口中的所有功能
T findOne(Specification spec);// 查询单个对象
List findAll(Specification spec);//查询列表
Page findAll(Specification spec, Pageable pageable); //分页查询列表,pageable:分页参数。
List findAll(Specification spec, Sort sort); //排序查询列表,Sort:排序参数
long count(Specification spec);//统计查询
在上面的所有方法中,都有 Specification 对象,它是查询条件对象,需要自定义自己的 Specification 实现类,需要实现如下的方法:
Predicate toPredicate(Root root, CriteriaQuery<?> query, CriteriaBuilder cb);
controller 实现多条件查询
/**
* 多条件分页查询分页查询 http://localhost:8080/page/limit
*
* @param student * @return
*/
@RequestMapping("/page/limit")
public Object getPageLimit() {
Integer limit=10;
Integer index=1;
String name="张3";
PageRequest page=PageRequest.of(index-1, limit);
Specification<Student> spec=new Specification<Student>() {
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
// TODO Auto-generated method stub
Predicate pc=criteriaBuilder.conjunction();
List<Expression<Boolean>> es=pc.getExpressions();
es.add(criteriaBuilder.like(root.get("name"), "%"+name+"%"));
return pc;
}
};
return repository.findAll(spec, page);
}
StudentRepository接口需要继承的
//接口 StudentRepository,并继承 JpaRepository 接口 JpaSpecificationExecutor接口
public interface StudentRepository extends JpaRepository<Student, Integer>,JpaSpecificationExecutor<Student>
1
自定义查询
一个字段
Repository:(这里省略Service层)
package com.qianyucc.blog.repository;
import com.qianyucc.blog.model.*;
import org.springframework.data.jpa.repository.*;
import java.util.*;
/**
* @author lijing
* @date 2019-08-05 14:28
* @description 文章数据库访问层
*/
public interface ArticleRepository extends JpaRepository<Article,Long>,JpaSpecificationExecutor<Article> {
@Query(value = "select distinct categories from article",nativeQuery = true)
// 这里注意返回值用String类型接收
List<String> findAllCategories();
}
这个叫绝绝子,这个返回值类型,我是真不会写,太牛了
多个字段
只需修改Repository,注意现在的返回值为List<Map<String,Object>>
public interface ArticleRepository extends JpaRepository<Article,Long>,JpaSpecificationExecutor<Article> {
@Query(value = "select author,categories from article",nativeQuery = true)
List<Map<String,Object>> findAllCategories();
}
- 原生 SQL 查询:nativeQuery=true 开启原生SQL
idea注释
@GetMapping和@PostMapping注解的区别
1 @RequestMappingMap
使用@RequestMappingComments 将 URL Map 到整个类或特定的处理程序方法上。 类级别的 Comments将特定的请求路径(或路径模式)Map 到表单控制器上,其他方法级别的 Comments 使特定的 HTTP 方法请求方法(“ GET”,“POST”等)的主 Map 范围变窄。 @RequestMapping默认情况下 Map 了所有 HTTP 方法。使用@RequestMapping(method=GET)或@GetMapping缩小 Map 范围。
@RequestMapping有8个属性。
value:指定请求的实际地址。
method:指定请求的method类型(GET,POST,PUT,DELETE)等。
consumes:指定处理请求的提交内容类型(Context-Type)。
produces:指定返回的内容类型,还可以设置返回值的字符编码。
params:指定request中必须包含某些参数值,才让该方法处理。
headers:指定request中必须包含某些指定的header值,才让该方法处理请求。
2 由@RequestMapping 变体组成
@GetMapping
用于将HTTPGET请求映射到特定处理程序方法的注释。具体来说,@GetMapping是一个作为快捷方式的组合注释@RequestMapping(method = RequestMethod.GET)。
@PostMapping
@PostMapping是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写用于将HTTP POST请求映射到特定处理程序方法的注释。
类似的还有
@PutMapping
@DeleteMapping
@PatchMapping
@PostMapping和@GetMapping都可以用@RequestMapping代替,如果怕在映射的时候出错,可以统一写@RequestMapping,当然这样写的话也有缺点,还是建议分开写。
但是请求方式需要服务端保持一致,客户端是POST,服务端一定需要是POST。
## SpringDataJpa:JpaRepository增删改查 默认方法
使用默认方法
@Test
public void testBaseQuery() throws Exception {
User user=new User();
userRepository.findAll();
userRepository.findOne(1l);
userRepository.save(user);
userRepository.delete(user);
userRepository.count();
userRepository.exists(1l);
// …
}
## spring-boot项目增删改查,这个就是把yml、依赖、前端页面都加上了
## maven中的groupId和artifactId到底指的是什么?
## springboot+jpa自动建表
## JPA 通过注解自动生成表,添加 字段名、类型、注释
## jpa实体类生成mysql表及字段注解
## springboot启动后执行某个方法的三种实现方式,且不影响提供服务
## IDEA中Maven Project中的Lifecycle(生命周期)
## redis+rabbitmq关于docker-compose.yml文件
## Spring MVC学习-Spring MVC快速入门
## SVN服务端的安装步骤
## JSP运行原理和JSP中的HTTP请求响应模型以及MVC模式
## Spring源码分析(一):从哪里开始看spring源码(系列文章基于Spring5.0)