vue+springmvc前后端分离开发(五)(JPA映射与Validation)

为什么需要JPA?

  • jpa是用来映射领域类和物理表之间的关系的,有了jpa才能够真正意义上的将物理表中的内容提取到领域类中,以及将领域类中的内容映射到物理表中
  • 因此,我们需要安装jpa依赖,同样在pom.xml文件中直接添加就可以了
    jpa依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

JPA在领域类中的体现

  • 想要将一个领域类映射到物理表中,需要首先加上@Entity注解,添加到spring上下文管理之中
  • jpa需要领域类有一个有参的构造方法,所以需要在领域类上加上@RequiredArgsConstructor注解
  • jpa进行映射时会通过类名映射到对应的表,比如User类就对应user表,但是我们的表名叫做users,所以需要加上@Table(name = “users”)注解来指定表名
  • 同样字段也会映射到对应名字的字段,比如username就映射到username,但我们有些字段是驼峰式命名的,比如joinedDate,这时就需要加上@Column(name = “joined_date”)注解来指定字段名
  • jpa需要指定一个唯一id,在主键字段上要加上@Id注解,如果id是按照某种方式生成的,还需要加上@GeneratedValue注解
  • 下面给出User类的一个样例
package kmhc.domain.user;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.OneToMany;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
@Entity
@Table(name = "users")
public class User implements UserDetails {

	/**
	 * 
	 */
	// Serializable
	private static final long serialVersionUID = 1L;

	// username primary key
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	// username
	private String username;
	
	// password
	private String password;
	
	// is active default is true
	private boolean enabled = true;
	
	// first name
	@Column(name = "first_name")
	private String firstName;
	
	// last name
	@Column(name = "last_name")
	private String lastName;
	
	// gender default is 0
	private short gender;
	
	// phone
	private String phone;
	
	// email
	private String email;
	
	// icon
	private String icon;
	
	// birthday
	private Date birthday;
	
	// joined date
	@Column(name = "joined_date")
	private Date joinedDate;
	
	@PrePersist
	void joinedDate() {
		this.joinedDate = new Date();
	}
	
	// authorities
	@OneToMany(targetEntity = Authority.class, mappedBy = "user", cascade = { CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER)
	private List<Authority> authorities;

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		List<GrantedAuthority> auths = new LinkedList<>();
		for (Authority authority : this.authorities) {
			auths.add(new SimpleGrantedAuthority(authority.getAuthority()));
		}
		return auths;
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return this.enabled;
	}
}

JPA的一对多、多对一、多对多

  • 以上三种是jpa中比较常用的表之间关系的映射
  • 一对多和多对一不一定是成对出现的,有的时候只需要其中一方就可以了
  • 下面开始讲解这些关系的核心要素

@OneToMany

  • 一对多,经常出现在User类中,我们需要得知这个user都具备哪些权限
  • 一般作用在一个List上
  • 有几个关键属性
    • targetEntity(指定多的那一方对应的类,可以不写)
    • mappedBy(指定本类,在多的那一方的类中,属性名是什么)
    • cascade(指定级联关系,在一对多中一般只要MERGE和REMOVE两种就可以)
    • fetch(指定懒加载还是快加载,默认懒加载)

@ManyToOne

  • 多对一,一般来说在多的那一方必然存在,经常用在获取某个文章的作者
  • 有几个关键属性
    • targetEntity(指定一的那一方对应的类,可以不写)
    • optional(一的那一方是否是可选的,一般是false,即必须要有)
  • @JoinColumn
    • 这个注解一般是和@ManyToOne同时作用在一个属性上的
    • @JoinColumn(name = “user_id”)代表这个属性在真实物理表中的字段名叫做user_id,不加这个注解默认会以属性名加主键名的方式代表字段名

@ManyToMany

  • 多对多,当两个领域类存在多对多关系的时候就要有这个注解,由其中一方维护即可
  • 一般作用在List上
  • 有几个关键属性
    • targetEntity(指定另一方对应的类,可以不写)
  • @JoinTable
    • 这个注解一般是和@ManyToMany同时作用在一个属性上的
    • @JoinTable(name = “group_members”, joinColumns = @JoinColumn(name = “group_id”), inverseJoinColumns = @JoinColumn(name = “user_id”))
    • 可以看到,此注解不但制定了多对多对应的表名,还用了@JoinColumn注解
    • joinColumns属性代表本类所代表的外键
    • inverseJoinColumns属性代表另一个类所代表的外键

Validation

  • 现在用了jpa进行映射,但是无法保证这个映射一定能够满足数据库用户自定义完整性的要求,因此我们需要安装java validation依赖
    validation依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • 同样Validation也是用了注解的方式对属性进行验证,不满足要求的后端会直接返回一个400状态码
  • 如果不在类上加上@Validate注解,是不会进行自动验证的
  • 有关jpa和validation的结合请看下面代码

JPA和Validation的完整代码

package kmhc.domain.user;

import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.persistence.OneToMany;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
@Entity
@Table(name = "users", uniqueConstraints = { @UniqueConstraint(columnNames = { "username" }) })
public class User implements UserDetails {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// id primary key
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	// username unique
	@NotNull
	private String username;

	// password
	@Size(min = 6, message = "password must be at least 6 characters!")
	private String password;

	// is active default is true
	private boolean enabled = true;

	// first name
	@Column(name = "first_name")
	private String firstName;

	// last name
	@Column(name = "last_name")
	private String lastName;

	// gender default is 0
	private short gender = 0;

	// phone
	private String phone;

	// email
	@Email
	private String email;

	// icon
	private String icon;

	// birthday default is current
	private Date birthday = new Date();

	// joined date default is current
	@Column(name = "joined_date")
	private Date joinedDate = new Date();

	// authorities
	@OneToMany(targetEntity = Authority.class, mappedBy = "user", cascade = { CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER)
	private List<Authority> authorities;

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		List<GrantedAuthority> auths = new LinkedList<>();
		for (Authority authority : this.authorities) {
			auths.add(new SimpleGrantedAuthority(authority.getAuthority()));
		}
		return auths;
	}

	@Override
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return this.enabled;
	}
}
package kmhc.domain.user;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
@Entity
@Table(name = "authorities")
public class Authority implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -1271128647094978200L;

	// id primary key
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	// authority name
	@NotNull
	private String authority;
	
	// user id
	@ManyToOne(targetEntity = User.class, optional = false)
	@JoinColumn(name = "user_id")
	private User user;
}
package kmhc.domain.user;

import java.io.Serializable;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.persistence.JoinColumn;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
@Entity
@Table(name = "user_groups")
public class Group implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -63681634856481619L;

	// id
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	// group name
	@NotNull
	@Column(name = "group_name")
	private String groupName;
	
	// group authorities
	@OneToMany(targetEntity = GroupAuthority.class, mappedBy = "group", cascade = { CascadeType.MERGE, CascadeType.REMOVE })
	private List<GroupAuthority> authorities;
	
	// group users
	@ManyToMany(targetEntity = User.class)
	@JoinTable(name = "group_members", joinColumns = @JoinColumn(name = "group_id"), inverseJoinColumns = @JoinColumn(name = "user_id"))
	private List<User> users;
}
package kmhc.domain.user;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
@Entity
@Table(name = "group_authorities")
public class GroupAuthority implements Serializable {


	/**
	 * 
	 */
	private static final long serialVersionUID = -5792431421556924268L;

	// id
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	// authority name
	@NotNull
	private String authority;
	
	// group name
	@ManyToOne(targetEntity = Group.class, optional = false)
	@JoinColumn(name = "group_id")
	private Group group;
}

至此,领域类中的JPA和Validation已完成,但是仍然没有数据库的连接动作和结果集的提取。下一节我们会讲解repository以及回到spring security上来

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: vue springboot前后分离开发实战pdf是一本介绍如何使用Vue和Spring Boot进行前后分离开发的实战指南。本书详细讲解了如何使用Vue框架搭建前应用,以及如何利用Spring Boot框架构建后应用,旨在帮助读者掌握前后分离开发的技术和方法。 在这本书中,作者首先介绍了前后分离开发的概念和背景,解释了为什么前后分离可以带来更好的开发体验和效率。接着,作者详细介绍了Vue框架的基本概念和使用方法,包括组件化开发、路由管理、状态管理等方面的内容。读者可以通过跟随书中的示例代码,逐步学习并实践Vue框架的应用。 在后半部分,作者重点介绍了Spring Boot框架的使用。读者将学习如何使用Spring Boot快速搭建后应用,并了解如何通过RESTful API与前应用进行数据交互。此外,作者还介绍了Spring Security、Spring Data JPA等常用的配套技术,帮助读者构建安全可靠的后应用。 本书不仅提供了理论知识,还提供了大量的实战案例和实例代码。读者可以跟随书中的示例项目逐步实践,从而更好地掌握Vue和Spring Boot的开发技巧。此外,本书还涉及了一些项目管理和部署的内容,帮助读者了解如何将前后分离的应用部署到生产环境中。 总而言之,vue springboot前后分离开发实战pdf是一本适合想要学习并实践前后分离开发开发人员的实用指南,通过学习本书,读者将获得丰富的知识和经验,能够独立设计和开发前后分离的应用程序。 ### 回答2: 《Vue SpringBoot前后分离开发实战PDF》这本书是一本关于前后分离开发实践的指南。它结合了Vue和SpringBoot两个流行的开发框架,帮助开发者更好地理解和应用这两个技术。 在书中,作者首先介绍了前后分离的概念和优势。前后分离开发可以提高开发效率和协作性,同时也能提供更好的性能和扩展性。然后,作者详细介绍了Vue框架的基本知识和使用方法,包括Vue的搭建、组件的创建和组织等。读者可以通过实际的案例来学习和练习。 接着,作者转向SpringBoot框架的介绍和使用。SpringBoot是一个轻量级的Java开发框架,可以快速构建和部署应用程序。作者讲解了如何使用SpringBoot创建RESTful API,以及如何与Vue进行交互。 在书的后半部分,作者提供了一些实战案例和示例代码。这些案例涵盖了常见的前后分离开发场景,如用户管理、权限控制、数据交互等。通过这些案例,读者可以了解到如何将Vue和SpringBoot无缝地结合起来,构建强大的应用程序。 总的来说,《Vue SpringBoot前后分离开发实战PDF》是一本非常实用的书籍。它不仅系统地介绍了Vue和SpringBoot的基础知识和使用方法,还提供了丰富的实战经验和案例。对于想要掌握前后分离开发技术的开发者来说,这本书是一个很好的学习资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值