JPA
定义:java持久化API规范(抽象的定义)
实现:hibernate,toplink等。
JPA与JDBC的关系
相同点:官方数据持久化的技术规范。
不同点:
出现时间:JDBC是最早数据持久化方案,慢慢出现EJB,JPA是最新的。
架构:JPA在JDBC之上。
JPA比JDBC更加简单高效。
Java与关系型数据库的持久化方案
. 1.JDBC (官方)
2.EJB (官方)
3.MyBatis(社区)
4.Hibernate(社区)
5.JDO(社区)
6.JPA (官方)
7....(社区)
JDBC太繁琐,低效。EJB过分复杂。因此开发人员自发的创建了MyBatis,Hibernate之类的持久化技术,
大量开发人员不使用官方技术规范,官方从社区吸取经验,定义新的规范JPA,底层实现还是Hibernate
或toplink之类的第三方框架。
MyBatis与JPA(Hibernate)
mybatis是SQL映射。半自动化,写SQL语句
hibernate是对象关系映射。自动化,不写SQL,调用方法,方法不够时,写HQL。
初步上手Hibernate简单,如果业务复杂,需要性能优化,学习曲线上升高。不可控。
mybatis总体上更加简单,关注点依旧在SQiL。
国外JPA多,国内MyBatis多。
JPA是官方的ORM(对象关系映射)的API规范
对象与表的映射
对象所在类名与表之间的映射。
对象中的字段与表中的列之间的映射
对象之间的关系到表与表之间的关系的映射
一对一
一对多
继承
接下来让我们通过代码来认识JPA
首先选择需要的依赖
工程目录
Dept.java
package com.newer.jpa2.pojo;
/**
* 部门
*/
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "dept")
public class Dept {
/**
* 主键字段,数据库中生成的值,策略IDENTITY(MySQL自动增长)
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "title")
private String title;
@Column(name = "loc")
private String loc;
public Dept() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept [id=" + id + ", title=" + title + ", loc=" + loc + "]";
}
}
Job.java
package com.newer.jpa2.pojo;
/**
* 职位
*/
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "job")
public class Job {
/**
* 主键字段,数据库中生成的值,策略IDENTITY(MySQL自动增长)
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "title")
private String title;
@Column(name = "info")
private String info;
public Job() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return "Job [id=" + id + ", title=" + title + ", info=" + info + "]";
}
}
Staff.java
package com.newer.jpa2.pojo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
/**
* 实体(JPA)
* @author Admin
*
*/
@Entity
public class Staff {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String name;
String phone;
@OneToOne
@JoinColumn(referencedColumnName = "id")
Dept dept;
@OneToOne
@JoinColumn(referencedColumnName = "id")
Job job;
public Staff() {
}
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;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public Job getJob() {
return job;
}
public void setJob(Job job) {
this.job = job;
}
@Override
public String toString() {
return "Staff [id=" + id + ", name=" + name + ", phone=" + phone + ", dept=" + dept + ", job=" + job + "]";
}
}
application.properties
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/jpa?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.http.log-request-details=true
logging.level.web=debug
#JPA
#根据实体(POJO)的注解自动生成 SQL DDL 创建表结构
spring.jpa.generate-ddl=true
#显示底层执行的 SQL 语句
spring.jpa.show-sql=true
通过上面的代码,我们不需要手动去创建数据库的表,程序会帮我们自动创建表。这也是JPA的优点之一,自动化。
DeptRepository.java
package com.newer.jpa2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.newer.jpa2.pojo.Dept;
@Repository
public interface DeptRepository extends JpaRepository<Dept, Long> {
// 基本操作已实现了
}
JobRepository.java
package com.newer.jpa2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.newer.jpa2.pojo.Job;
@Repository
public interface JobRepository extends JpaRepository<Job, Long>{
}
StaffRepository.java
package com.newer.jpa2.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.newer.jpa2.pojo.Staff;
@Repository
public interface StaffRepository extends JpaRepository<Staff, Long> {
}
上面的是数据访问所需的接口。
DeptController.java
package com.newer.jpa2.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.newer.jpa2.pojo.Dept;
import com.newer.jpa2.repository.DeptRepository;
@RestController
@RequestMapping("/api/dept")
public class DeptController {
@Autowired
DeptRepository deptRepository;
@GetMapping
public List<Dept> findAll(){
return deptRepository.findAll();
}
@PostMapping
public Dept save(@RequestBody Dept dept) {
return deptRepository.save(dept);
}
@GetMapping("/{id}")
public Dept load(@PathVariable Long id) {
return deptRepository.findById(id).get();
}
@DeleteMapping("{id}")
public void remove(@PathVariable Long id) {
deptRepository.deleteById(id);
}
@PutMapping("{id}")
public Dept updata(@PathVariable Long id,@RequestBody Dept dept) {
// 设置id
dept.setId(id);
return deptRepository.saveAndFlush(dept);
}
}
JobController.java
package com.newer.jpa2.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.newer.jpa2.pojo.Job;
import com.newer.jpa2.repository.JobRepository;
@RestController
@RequestMapping("/api/job")
public class JobController {
@Autowired
JobRepository jobRepository;
@GetMapping
public List<Job> findAll(){
return jobRepository.findAll();
}
@PostMapping
public Job create(@RequestBody Job job) {
return jobRepository.save(job);
}
@GetMapping("/{id}")
public Job load(@PathVariable Long id) {
return jobRepository.findById(id).get();
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
jobRepository.deleteById(id);
}
@PutMapping("/{id}")
public Job update(@PathVariable Long id,@RequestBody Job job) {
job.setId(id);
return jobRepository.saveAndFlush(job);
}
}
StaffController.java
package com.newer.jpa2.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.newer.jpa2.pojo.Staff;
import com.newer.jpa2.repository.StaffRepository;
@RestController
@RequestMapping("/api/staff")
public class StaffController {
@Autowired
StaffRepository staffRepository;
@GetMapping
public List<Staff> findAll(){
return staffRepository.findAll();
}
@PostMapping
public Staff create (@RequestBody Staff staff) {
return staffRepository.save(staff);
}
@GetMapping("/{id}")
public Staff load(@PathVariable Long id) {
return staffRepository.findById(id).get();
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
staffRepository.deleteById(id);
}
@PutMapping("{id}")
public Staff update(@PathVariable Long id,@RequestBody Staff staff) {
staff.setId(id);
return staffRepository.saveAndFlush(staff);
}
}
由于实现的只是基本的CRUD,可以不用到业务逻辑(service)。如果以后开发项目,会经常用到service。然后再通过Controller去操作数据。
HomeController.java(通过前端去访问服务端的数据),vue路由的实现也可以通过HTML 超链接 + Spring MVC 完成的路由。这篇博客就是用HTML 超链接 + Spring MVC 完成的路由。关于vue路由,有兴趣的小伙伴可以去前面的博客看。
package com.newer.jpa2.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* SPA 前后端分离(Vue Cli,Angular,JS,React),这个就不需要
*
* SSR 没有前后端分离(模板引擎,ajax,Vue),此处在进行视图的路由
* @author Admin
*
*/
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "index.html";
}
@GetMapping("/dept")
public String dept() {
return "dept.html";
}
@GetMapping("/staff")
public String staff() {
return "staff.html";
}
@GetMapping("/job")
public String job() {
return "job.html";
}
}
接下来是前端的代码
index.html
<!doctype html>
<html lang="en">
<head>
<title>JPA</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">JPA</a>
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId" aria-controls="collapsibleNavId"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsibleNavId">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item active">
<a class="nav-link" href="#">首页 <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="dept">部门</a>
</li>
<li class="nav-item">
<a class="nav-link" href="staff">员工</a>
</li>
<li class="nav-item">
<a class="nav-link" href="job">职位</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="text" placeholder="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
dept.html
<!doctype html>
<html lang="en">
<head>
<title>部门</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div class="jumbotron jumbotron-fluid py-3 mb-0">
<div class="container">
<h1 class="display-3">部门管理</h1>
</div>
</div>
<nav class="breadcrumb mt-0">
<a class="breadcrumb-item" href="/">首页</a>
<span class="breadcrumb-item active">部门</span>
</nav>
<div id="app" class="container-fluid">
<div class="row">
<div class="col-lg-4">
<!-- 表单 -->
<div class="card">
<div class="card-body">
<div class="form-group">
<label for="">部门名称</label>
<input
v-model="title"
type="text" class="form-control" name="" id="" aria-describedby="helpId"
placeholder="部门名称">
</div>
<div class="form-group">
<label for="">办公地点</label>
<input
v-model="loc"
type="text" class="form-control" name="" id="" aria-describedby="helpId"
placeholder="办公地点">
</div>
<button
@click="create"
type="button" class="btn btn-primary btn-lg btn-block">添加</button>
</div>
</div>
</div>
<div class="col-lg-8">
<!-- 表格 -->
<table class="table">
<thead>
<tr>
<th><input type="checkbox"></th>
<th>编号</th>
<th>名称</th>
<th>工作地点</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(dept, index) in deptList" :key="index">
<td><input type="checkbox" ></td>
<td >{{dept.id}}</td>
<td>{{dept.title}}</td>
<td>{{dept.loc}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
new Vue({
el:"#app",
data:{
title:'',
loc:'',
// 员工列表
deptList:[]
},
methods: {
// 创建部门的方法
create:function(){
let url='/api/dept';
params={
title:this.title,
loc:this.loc
};
axios.post(url,params)
.then(res => {
// console.log(res)
this.deptList.push(res.data);
})
.catch(err => {
console.error(err);
})
}
},
created() {
// Get /api/dept
axios.get('/api/dept')
.then(res => {
console.log(res)
this.deptList=res.data;
})
.catch(err => {
console.error(err);
})
},
})
</script>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
job.html
<!doctype html>
<html lang="en">
<head>
<title>职位</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div class="jumbotron jumbotron-fluid py-3 mb-0">
<div class="container">
<h1 class="display-3">职位管理</h1>
</div>
</div>
<nav class="breadcrumb mt-0">
<a class="breadcrumb-item" href="/">首页</a>
<span class="breadcrumb-item active">职位</span>
</nav>
<div id="app" class="container-fluid">
<div class="row">
<div class="col-lg-4">
<!-- 表单 -->
<div class="card">
<div class="card-body">
<div class="form-group">
<label for="">职位名称</label>
<input
v-model="title"
type="text" class="form-control" name="" id="" aria-describedby="helpId"
placeholder="职位名称">
</div>
<div class="form-group">
<label for="">职位信息</label>
<input
v-model="info"
type="text" class="form-control" name="" id="" aria-describedby="helpId"
placeholder="职位信息">
</div>
<button
@click="create"
type="button" class="btn btn-primary btn-lg btn-block">添加</button>
</div>
</div>
</div>
<div class="col-lg-8">
<!-- 表格 -->
<table class="table">
<thead>
<tr>
<th><input type="checkbox"></th>
<th>编号</th>
<th>名称</th>
<th>职位信息</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="(job, index) in jobList" :key="index">
<td><input type="checkbox" ></td>
<td >{{job.id}}</td>
<td>{{job.title}}</td>
<td>{{job.info}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
new Vue({
el:'#app',
data:{
title:'',
info:'',
// 部门列表
jobList:[]
},
methods: {
// 创建职位的方法
create:function(){
let url='/api/job';
let params={
title:this.title,
info:this.info
}
axios.post(url,params)
.then(res => {
console.log(res)
this.jobList.push(res.data);
})
.catch(err => {
console.error(err);
})
}
},
created() {
axios.get('/api/job')
.then(res => {
console.log(res)
this.jobList=res.data;
})
.catch(err => {
console.error(err);
})
},
})
</script>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
staff.html
<!doctype html>
<html lang="en">
<head>
<title>员工</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div class="jumbotron jumbotron-fluid py-3">
<div class="container">
<h1 class="display-3">员工管理</h1>
</div>
</div>
<nav class="breadcrumb mt-0">
<a class="breadcrumb-item" href="/">首页</a>
<span class="breadcrumb-item active">部门管理</span>
</nav>
<div id="app" class="container-fluid">
<div class="row">
<div class="col-lg-4">
<!-- 表单 -->
<div class="card">
<div class="card-body">
<div class="form-group">
<label for="">姓名</label>
<input v-model="name" type="text" class="form-control" name="" id=""
aria-describedby="helpId" placeholder="姓名">
</div>
<div class="form-group">
<label for="">联系方式</label>
<input v-model="phone" type="text" class="form-control" name="" id=""
aria-describedby="helpId" placeholder="联系方式">
</div>
<div class="form-group">
<label for="">职位</label>
<select v-model="jobId" class="form-control">
<option v-for="(job, index) in jobList" :key="index" :value="job.id">
{{job.title}}
</option>
</select>
</div>
<div class="form-group">
<label for="">部门</label>
<select v-model="deptId" class="form-control">
<option v-for="(dept, index) in deptList" :key="index" :value="dept.id">
{{dept.title}}
</option>
</select>
</div>
<button @click="create" type="button" class="btn btn-primary btn-lg btn-block">添加</button>
</div>
</div>
</div>
<div class="col-lg-8">
<!-- 表格 -->
<table class="table">
<thead>
<tr>
<th><input type="checkbox"></th>
<th>编号</th>
<th>姓名</th>
<th>联系方式</th>
<th>职位</th>
<th>部门</th>
<th>工作地点</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(staff, index) in staffList" :key="index">
<td><input type="checkbox"></td>
<td>{{staff.id}}</td>
<td>{{staff.name}}</td>
<td>{{staff.phone}}</td>
<td>{{staff.job.title}}</td>
<td>{{staff.dept.title}}</td>
<td>{{staff.dept.loc}}</td>
<td>
<button @click="edit(index)" type="button" class="btn btn-primary" data-toggle="modal"
data-target="#modelId">编辑</button>
<!-- Modal -->
<div class="modal fade" id="modelId" tabindex="-1" role="dialog"
aria-labelledby="modelTitleId" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">修改员工的信息:</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- 表单 -->
<div class="form-group">
<label for="">姓名</label>
<input v-model="editItem.name" type="text" class="form-control"
name="" id="" aria-describedby="helpId" placeholder="姓名">
</div>
<div class="form-group">
<label for="">联系方式</label>
<input v-model=" editItem.phone" type="text" class="form-control"
name="" id="" aria-describedby="helpId" placeholder="联系方式">
</div>
<div class="form-group">
<label for="">职位</label>
<select v-model="editItem.job_id" class="form-control">
<option v-for="(job, index) in jobList" :key="index" :value="job.id">
{{job.title}}
</option>
</select>
</div>
<div class="form-group">
<label for="">部门</label>
<select v-model="editItem.dept_id" class="form-control">
<option v-for="(dept, index) in deptList" :key="index" :value="dept.id">
{{dept.title}}
</option>
</select>
</div>
<div class="form-group">
<label for="">工作地点</label>
<select v-model="editItem.dept_id" class="form-control">
<option v-for="(dept, index) in deptList" :key="index" :value="dept.id">
{{dept.loc}}
</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-dismiss="modal">取消</button>
<button @click="update" type="button" class="btn btn-primary"
data-dismiss="modal">确定</button>
</div>
</div>
</div>
</div>
<button @click="del(staff.id)" type="button" class="btn btn-danger">删除</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
// 部门列表
deptList: [],
// 职位列表
jobList: [],
name: '',
phone: '',
deptId: '',
jobId: '',
// 员工列表
staffList: [],
// 更新
editIndex: 0,
editItem: {}
},
methods: {
// 创建员工
create: function () {
let url = '/api/staff';
let params = {
name: this.name,
phone: this.phone,
job: {
id: this.jobId
},
dept: {
id: this.deptId
}
};
axios.post(url, params)
.then(res => {
// console.log(res)
// this.staffList.push(res.data)
// 再次加载
axios.get('/api/staff')
.then(res => {
// console.log(res)
this.staffList = res.data;
})
.catch(err => {
console.error(err);
})
})
.catch(err => {
console.error(err);
})
},
// 删除员工
del: function (id) {
let url = `/api/staff/${id}`;
axios.delete(url)
.then(res => {
// console.log(res)
// 再次加载
axios.get('/api/staff')
.then(res => {
// console.log(res)
this.staffList = res.data;
})
.catch(err => {
console.error(err);
})
})
.catch(err => {
console.error(err);
})
},
// 编辑员工的方法
edit: function (i) {
// 获得更新的内容
this.editIndex = i;
this.editItem = {},
// console.log(this.staffList);
// staffList的内容赋给editItem
this.editItem.id = this.staffList[i].id;
this.editItem.name = this.staffList[i].name;
this.editItem.phone = this.staffList[i].phone;
this.editItem.dept_id = this.staffList[i].dept.id;
this.editItem.job_id = this.staffList[i].job.id;
// console.log(this.editItem);
console.log(this.staffList[i].dept.id);
console.log(this.staffList[i].job.id);
console.log(this.editItem);
},
// 更新员工
update: function () {
let url = `/api/staff/${this.editItem.id}`;
let params ={
name:this.editItem.name,
phone:this.editItem.phone,
dept:{
id:this.editItem.dept_id
},
job:{
id:this.editItem.job_id
}
}
axios.put(url, params)
.then(res => {
// console.log(res)
// 再次加载
axios.get(`/api/staff`)
.then(res => {
// console.log(res)
this.staffList=res.data;
})
.catch(err => {
console.error(err);
})
})
.catch(err => {
console.error(err);
})
}
},
created() {
// 加载部门信息
axios.get('/api/dept')
.then(res => {
// console.log(res)
this.deptList = res.data;
// 获得·默认的部门
this.deptId = this.deptList[0].id;
})
.catch(err => {
console.error(err);
}),
// 加载职位信息
axios.get('/api/job')
.then(res => {
// console.log(res)
this.jobList = res.data;
// 获得·默认的职位
this.jobId = this.jobList[0].id;
})
.catch(err => {
console.error(err);
}),
axios.get('/api/staff')
.then(res => {
// console.log(res)
this.staffList = res.data;
})
.catch(err => {
console.error(err);
})
},
})
</script>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
运行程序,然后我们就可以通过浏览器看到效果了
这个界面相当于Vue路由。可以跳转,不是通过超链接跳转的,那样太lowl了。Vue CLI 开发 SPA ,则 Vue 路由才是必须的。SPA 有且只有一个 html,在唯一的页面中组件替换渲染,地址栏路径的变换(表象)。
以staff为例,基本实现了staff表的CRUD操作。
到这里,关于JPA+Vue+axios实现员工管理系统(CRUD)就差不多结束了。有问题的小伙伴可以留言!!!