1. 数据持久化

 1.1 JPA 

在JPA 产生之前,围绕如何简化数据库操作的相关讨论已经是层出不穷,其中ORM 框架最为开发人员所关注。ORM是一种用于实现面向对象编程语言里不同类型系统的数据之间的转换的技术,它们将对象拆分成SQL 语句,从而来操作数据库。但是不同的ORM 框架在使用上存在比较大的差异,而JPA 规范就是为了解决这个问题:规范ORM 框架,使用ORM 框架统一的接口和用法。

最早的JPA 规范是由Java 官方提出的,随Java EE 5 规范一同发布。

1.2 实体

        通常,实体表示关系数据库中的表,井且每个实体实例对应于该表中的行。实体的持久状态通过持久化字段或持久化属性来表示,这些字段或属性使用对象/关系映射注解将实体和实体关系映射到基础数据存储中的关系数据。

1.2.1 实体类的要求

        ( 1 )类必须用@Entity 注解。
        ( 2 )类必须有一个public 或protected 的元参数的构造函数。该类可以具有其他构造函数。
        ( 3 )类不能声明为final 。没有方法的或持久化实例变量必须声明为final 。
        ( 4 )如果实体实例被当作值以分离对象方式进行传递(如通过会话Bean 的远程业务接口),
                则该类必须实现Serializable 接口。
        ( 5 )实体可以扩展实体类或者是非实体类,并且非实体类可以扩展实体类。
        ( 6 )持久化实例变量必须声明为private 、protected 或package-private ,并且只能通过实体类的

方法直接访问。客户端必须通过访问器或业务方法访问实体的状态。

举个例子:

package com.duxihu.demothymeleaf.domain;import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;@Entity
public class DemoUser {@Id //主键@GeneratedValue(strategy = GenerationType.IDENTITY)//自增长策略private Long id;private String name;private Integer age;protected DemoUser(){//无参构造函数;设为protected防止被直接使用}public DemoUser(Long id ,String name, Integer age) {this.id = id;this.name = name;this.age = age;}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 Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "DemoUser{" +"id=" + id +", name='" + name + '\'' +", age=" + age +'}';}
}

如果实体使用持久化属性, 实体必须遵循JavaBean 组件的方法约定。对于实体的每个持久化属性,都有一个getter 方法和setter方法。如果属性是布尔值,可以使用isProperty ,而不是getProperty 。持久化属性的对象/关系映射注解必须应用于getter方法。映射注解不能应用于注解为@Transient或标记为transient 的字段或属性。

1.2.2 在实体字段和属性中使用集合

                集合作为持久化字段和属性,必须使用受Java 集合支持的接口:

• java.util.Collection。

• java.util.Set 。

• java.util.List 。

• java. util.Map 。

如果实体的字段或属性由基本类型或可嵌入类的集合组成,请在字段或属性上使用@ElementCollection 注解。

@ElementCollectionprotectedSet<String>loverName =newHashSet<>();

  1.2.3 实体中的主键

                实体可以具有简单主键或复合主键。

简单主键使用@Id 注解来表示主键属性或字段。

当主键由多个属性组成时,使用复合主键,复合主键必须在主键类中定义,使用@Embeddedld和@IdClass来标识。

                主键或复合主键的属性或字段必须是以下Java 语言类型之一。
                     Java 基本数据类型。
                     Java 基本数据类型的包装类型。
                     java.lang.String 。
                     java.util.Date (时间类型应为DATE )。
                     java.sql.Date 
                     java.math.BigDecimal

java.math.Biglnteger

                    不应在主键中使用浮点类型。


                主键类必须满足以下要求

( 1 )类的访问控制修饰符必须是public 。
                    ( 2 ) 如果使用基于属性的访问, 主键类的属性必须为public 或protected 。
                    ( 3 )该类必须有一个公共默认构造函数。
                    ( 4 )类必须实现hashCode()方法和equals(Object  other)方法。
                    ( 5 )类必须是可序列化的。
                    ( 6 )复合主键必须被表示并映射到实体类的多个字段或属性,或者必须被表示井映射为可嵌
                            入类。
                    ( 7 ) 如果类映射到实体类的多个字段或属性, 则主键类中的主键宇段或属性的名称和类型必

须与实体类的名称和类型匹配.

            1.2.4 实体间的关系

( 1 ) 一对一   One to One

( 2 ) 一对多   One to Many

( 3 )  多对一  Many to One

( 4 ) 多对多   Many to Many

                    实体关系中的方向可以是双向的或单向的。

1. 双向关系 , 双向关系必须遵循以下规则:

( 1 )双向关系的反面必须通过使用@OneToOne  @OneToMany 或@ ManyToMany 注解的
                                    mappedBy元素引用其拥有方。mappedBy元素指定实体中作为关系所有者的属性或字段。
                            ( 2 )多对一双向关系的许多方面不能定义mappedBy 元素。许多方面总是关系的拥有方。
                            ( 3 )对于一对一双向关系,拥有侧对应于包含相应外键的一侧。
                            ( 4 )对于多对多双向关系,任一侧可以是拥有侧。

2. 单向关系

只有一个实体具有引用另一个实体的关系字段或属性.

       1.2.5 级联操作相关系

使用关系的实体通常依赖于关系中另一个实体的存在,比如用户详情是用户项的一部分 ,

如果用户被删除,用户详情也应该被删除,这称为级联删除关系。

实体的级联操作

                ALL  : ALL 级联操作将应用于父实体的相关实体。所有等同于指定cascade={DETACH,MERGE, PERSIST,                                    REFRESH, REMOVE}

DETACH:   如果父实体与持久化上下文分离,则相关实体也将被分离

MERGE : 如果父实体被合并到持久化上下文中,则相关实体也将被合并

PERSIST  : 如果父实体被持久化到持久化上下文中,则相关实体也将被持久化

REFRESH : 如果父实体在当前持久化上下文中被刷新,相关实体也将被刷新

REMOVE : 如果父实体从当前持久化上下文中删除,相关实体也将被删除

            级联删除关系使用@OneToOne 和@OneToMany 关系的cascade=REMOVE 元素指定。例如,

            @OneToMany(cascade=REMOVE , mappedBy=”User ”)public Set<UserNumbers> getNumbers () { return numbers ; }

 删除关系中的“孤儿”

                    @OneToMany 和@oneToOne 中的orphanRemoval 属性采用布尔值,默认值为false 。修改为true,则在删除用户后默认删除用户妻子们;

    @OneToMany(mappedBy="User", orphanRemoval="true")
 public List <UserWifes> getWifes() { ... }

1.2 Spring Data JPA 是对JPA 规范的实现。

对于普通开发者而言,自己实现应用程序的数据访问层是一件极其烦琐的过程。必须编写太多的样板代码来执行简单查询、分页和审计。

 Spring Data JPA 包含如下特征。
( 1 )基于Spring 和JPA 来构建复杂的存储库。
( 2 )支持Querydsl谓词,因此支持类型安全的JPA查询。
( 3 )域类的透明审计。
( 4 ) 具备分页支持、动态查词执行、集成自定义数据访问代码的能力。
( 5 )在引导时验证@ Query 带注释的查询。
( 6 )支持基于XML 的实体映射。

( 7 )通过引人@EnableJpaRepositories 来实现基于JavaConfig 的存储库配置。

如何使用Spring Data JPA,首先引入依赖

<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>1.10.5.RELEASE</version></dependency>

对于底层数据存储的管理,通常使用标准CRUD 功能的资惊库来实现。

使用Spring Data 声明,这些查询将会变得简单,只需要4 步过程

            1. 声明扩展Repository或子接口

            2 . 在接口上声明查询方法

            3. 为这些接口创建代理实例

            

例如一下只需声明继承自Spring Data JPA 中的接口,就能自动实现通过名称来模糊查询的方法,而无需自己去实现。

public interfaceUserRepository extendsJpaRepository<User ,Long>{List<User>findUsersByNameLike(String name);}

通常,存储库接口将会扩展Repository 、CrudRepository 或PagingAndSortingRepository 等这些Spring Data 接口。另外,如果不想继承Spring Data 接口,还可以在接口上添加@RepositoryDefinition 注解, 用以声明这是一个Repos itory 接口。

3. Spring Data JPA 与Hibernate 、Spring Boot 集成

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>

     1.定义实体

修改User 类,参考JPA 的规范,将其修改成为实体。

( 1 ) User 类上增加了@Entity 注解,以标识其为实体。
                    ( 2 ) @Id 标识id 字段为主键。
                    ( 3 ) @GeneratedValue(strategy=GenerationType. IDENTITY)标识id 字段,以便使用数据库的自
                               增长字段为新增加的实体的标识。这种情况下需要数据库提供对自增长字段的支峙, 一般的数据库
                             (如HSQL 、SQL Server 、MySQL 等)都能够提供这种支持。
                    ( 4)应JPA 的规范要求,设置无参的构造函数protected User() {},并设为protected ,防止直
                                接被使用。

( 5)重写toString 方法,将User 信息自定义输出。

packagecom.duxihu.demothymeleaf.domain;importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.GenerationType;importjavax.persistence.Id;@Entity//实体public classUser {@Id@GeneratedValue(strategy =GenerationType.IDENTITY)//自增长策略privateLong id;//唯一标识privateString name;privateString email;protectedUser() {//无参默认构造器}publicUser(Long id,String name,String email) {this.id =id;this.name =name;this.email =email;}publicLong getId() {returnid;}public voidsetId(Long id) {this.id =id;}publicString getName() {returnname;}public voidsetName(String name) {this.name =name;}publicString getEmail() {returnemail;}public voidsetEmail(String email) {this.email =email;}@OverridepublicString toString() {return"User{"+"id="+id +", name='"+name +'\''+", email='"+email +'\''+'}';}}

2 .修改资源库

修改用户资源库的接口,继承CrudRepository 。由于Spring Data JPA 已经帮助用户做了实现,因此,用户不需要做任何实现,甚至都无须在UserRepository 中定义任何方法

public interfaceUserRepository extendsCrudRepository<User ,Long>{}

3. 修改控制器

@RestController@RequestMapping("/user")public classUserController {@AutowiredprivateUserRepository userRepository;//查词所有用户@GetMapping("/userlist")publicModelAndView userList(Model model){model.addAttribute("userList",userRepository.findAll());model.addAttribute("title","用户管理");return  newModelAndView("user/list","userModel",model);}//根据id查询用户@GetMapping("{id}")publicModelAndView view(@PathVariable("id")Long id,Model model){Optional<User>user=userRepository.findById(id);model.addAttribute("user",user.get());model.addAttribute("title","查看用户");return newModelAndView("user/view","userModel",model);}//获取创建表单页面@GetMapping("/form")publicModelAndView createForm(Model model){model.addAttribute("user",newUser(null,null,null));model.addAttribute("title","创建用户");return newModelAndView("user/form","userModel",model);}//保存用户@PostMappingpublicModelAndView saveOrUpdateUser(User user){user =userRepository.save(user);return newModelAndView("redirect:/user/userlist");}//根据id删除用户@GetMapping(value ="delete/{id}")publicModelAndView delete(@PathVariable("id")Long id){userRepository.deleteById(id);return newModelAndView("redirect:/user/userlist");}//修改用户界面@GetMapping(value ="edit/{id}")publicModelAndView editForm(@PathVariable("id")Long id,Model model){Optional<User>user=userRepository.findById(id);model.addAttribute("user",user);model.addAttribute("title","编辑用户");return newModelAndView("user/form","userModel",model);}}

    

       使用MySQL 数据库

                    首先,创建名为test的数据库,编码为UTF-8 ,修改application.properties文件,增加数据库连接

# DataSourcespring.datasource.url=jdbc:mysql://localhost/test?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8#注意不是spring.datasource.data-username#注意不是spring.datasource.data-passwordspring.datasource.username=testspring.datasource.password=testspring.datasource.driver-class-name=com.mysql.jdbc.Driver

# JPAspring.jpa.show-sql = true#每次应用启动,都会主动删除井创建数据库表spring.jpa.hibernate.ddl-auto=create-drop

其中spring.datasource.driver-class-name根据你当前mysql版本会有所不同。

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

     5.7 以上的 mysql 要注意在url中增加 useSSL=false&serverTimezone=UTC选项

     连接数据库的用户名和密码是 spring.datasource.username而不是spring.datasource.data-username。

启动项目

        可以发现, Hibernate 会自动在test数据库中创建表user。

通过浏览器访问http://localhost:8080/useruserlist可以看到项目的运行效果.

基于SpringBoot开发一套完整的项目(四)准备工作相关推荐

  1. 基于SpringBoot开发一套完整的项目(一)准备工作

    基于SpringBoot开发一套完整的项目(一)准备工作 1.1 SpringBoot简介 ① 为所有Spring 开发提供一个更快更广泛的人门体验. ② 零配置.无冗余代码生成和XML 强制配置,遵 ...

  2. 基于Java开发一套完整的区块链系统(附源码)

    来源:https://blog.csdn.net/victory_long 前言 近几年区块链概念越来越火,特别是区块链技术被纳入国家基础设施建设名单后,各大企业也开始招兵买马,对区块链技术进行研究, ...

  3. 基于Java开发一套完整的区块链系统(附完整源码)

    前言 近几年区块链概念越来越火,特别是区块链技术被纳入国家基础设施建设名单后,各大企业也开始招兵买马,对区块链技术进行研究,从各大招聘网站的区块链职位来看,薪资待遇都很不错,月薪30K到80K的都有, ...

  4. 基于Java开发一套完整的区块链系统

    一.区块链技术理论基础 1.基本概念 (1)区块链 从技术层面来看,区块链是由包含交易信息的区块按照时间顺序从后向前有序链接起来的数据结构. 从应用层面来说,区块链是一个分布式的共享账本和数据库,具有 ...

  5. java 快递项目_基于SpringBoot开发的Java快递代拿系统

    该项目基于 [基于SSM开发的Java快递代拿系统] 项目全面升级,使用当前最为流行的 SpringBoot 框架,相关技术栈全面更新!是您深入学习 SpringBoot 开发的最佳实践! 相关技术栈 ...

  6. 分享Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站

    这是个什么的项目? 使用 Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站. 博客线上地址:www.boblog.com Github地址:https: ...

  7. 图片管理系统源码_「程序员分享」基于SpringBoot开发的天猫商城源码

    前言 大家好,我是程序员it分享师,应粉丝的要求,今天给大家带来一个基于Springboot开发的天猫商城的源码! 使用技术 天猫商城系统使用的是Spring,SpringMvc,SpringBoot ...

  8. boot客户管理系统源码_「计算机毕设」基于SpringBoot开发的仓库管理系统

    前言 大家好,我是it分享师,今天给大家带来一个计算机的毕设项目.基于Springboot开发的仓库管理系统,底层权限控制已经基于shiro实现了,直接可以作为二次开发框架使用! 使用技术 本套系统采 ...

  9. 基于Springboot开发实现二手交易商城

    作者主页:编程指南针 作者简介:Java领域优质创作者.CSDN博客专家 .掘金特邀作者.多年架构师设计经验.腾讯课堂常驻讲师 主要内容:Java项目.毕业设计.简历模板.学习资料.面试题库.技术互助 ...

最新文章

  1. 【v2.x OGE-example 第二章(第二节) 修改器的使用】
  2. RabbitMQ的安装(linux篇)
  3. Android中用 adb 命令操作数据库
  4. [LeetCode] Excel Sheet Column Number
  5. 关于ios app发布的中间证书的要求--解决WWDR证书过期方案
  6. (转)Linux I/O 调度方法
  7. NYOJ 257 郁闷的C小加(一)
  8. 利用 LotusScript 灵活操作 Lotus Notes 富文本域
  9. 链接列Uva 6176 Faulhaber's Triangle
  10. 【CF666E】Forensic Examination - 广义后缀自动机+线段树合并
  11. android7.0 netd与netlink的framework,kernel通信流程
  12. 3h精通OpenCV(一)- 读取图像视频与网络摄像头
  13. paip.修复文件关联总结
  14. 20220626-JAVA高德地图天气API调用总结
  15. 阿里巴巴的26款超神Java开源项目!
  16. ASP编程实现各家快递公司订单状态查询
  17. 按钮 加加加 减减减
  18. matlab 周期性边界,PID控制器阶跃响应的分析(基于MATLAB仿真的实验):
  19. Camtasia如何给视频或者图片调色
  20. UDP进程terminated

热门文章

  1. Dark GDK 初体验
  2. 【硬件】机器人平台搭建
  3. sklearn聚类之—KMeans
  4. 使用Lucene开发简单的站内新闻搜索引擎(环境的搭建)
  5. 嵌入式三级知识点分类
  6. 环信IM即时通讯的简单集成
  7. 数据与程序的物理独立性、数据与程序的逻辑独立性、为什么数据库系统具有数据与程序的独立性?
  8. CSS页面布局及排版
  9. Linux查看服务器的cpu和内存的硬件信息
  10. 2021年广西甘蔗播种面积、产量及进口情况分析:广西甘蔗产量占全国甘蔗总产量的68.56%[图]