第一部分:实现域模型
1.一些基本理论
域模型是和持久化是密不可分的概念。通常,开发企业项目的第一个步大都就是创建域模型,即列出域中的实体并且定义实体之间的关系。(当然这基本说的是领域建模,好多公司的项目还是采用的数据库建模的形式。)
1.1域模型的相关概念
域模型的四个参与者:对象、关系、关系多样性和关系的可选性。
1》 对象
与java对象一样,域模型可以同时具有行为(在java在的方法)和状态(java的实体变量)
2》 关系
从java角度来看,关系表现为一个对象引用另一个对象。
充血域模型与贫血域模型
域模型实际上被持久化到数据库中,数据库建模经常和域建模是同义的,域对象包含属性(映射到数据库表的列)而非行为,这种类型的建模被称为贫血模型。
充血模型封装对象的属性、行为,并且利用面向对象实用程序设计方法。(比如继承、多态和封装)。域模型充血度越高,就越难以映射到数据库。
1.2 Ejb3 java持久化API
Ejb3java持久化API是元数据驱动的pojo技术。也就是说,为了把java对象中的数据保持到数据库中,我们的对象不必实现接口、扩展类,或采用框架模式。
(简单的java对象实际就是普通的javabean是使用pojo名称是为了避免和ejb混淆起来)
声明:如果你熟悉sql和jdbc并且喜欢通过自己动手的便利方式得到控制权和灵活性,那么O/R的成熟、技巧和自动化形式可能不适合你。如果情况是这样,那么你应该多了解Spinrg JdbcTemplate(这个我不喜欢用)和iBATIS(这个框架应该对你对对象的理解要求低很多)。可是我要警告您,java本身就是对象化的语言,我们要完美化,就要一切为对象。
2.使用JPA实现域对象
本章意在描述域对象的实现过程,下一张将详细介绍如何使用对象-关系映射把我们创建的实体和关系映射到数据库中。
(当然现在JPA不仅仅是EJB3值得骄傲的地方,其它好多公司也相继实现了JPA规范,做出了很多优秀的orm框架。如:hibernate、openjpa、toplink等。并且规范的好处就在于,你只要完全按照规范来写代码,这些框架你可以随意更换,并是不更改代码的前提下。)
书签:下面我们主要说的是如何定义一个实体bean,也就是如何把你的POJO映射为数据库对象。
2.1 @Entity
@Entity注解,它把POJO转换为实体。(以后我们常叫这样的POJO为实体Bean)
(jpa主要是支持注解的形式,简单是说也就是使用注解对你对象化的POJO进行声明表示,生成对应的数据库和对数据库进行对象化的封装。
那么,我们学习JPA也就无非是学习几个注解,并且通过我们对对象的理解,标识对象的关系等。我们常用的注解无法就二三十个注解,所以JPA会让你感觉原来那么简单)
package cn.partner4java.bean.part2_1;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
String userId;
String username;
String email;
}
2.2持久化实体数据
?我们注解标识的位置:
持久化分为两种:基于字段与基于属性的持久化。
使用实体的字段或实体变量定义的O/R映射被称为基于字段的访问,也就是注解标注在字段上面。当然基于字段如果你省略了get和set,也可以生产成功。
如:
package cn.partner4java.bean.part2_1;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
String userId;
String username;
String email;
}
基于属性,必须标注在get方法上面,而非set。
如:
package cn.partner4java.bean.part2_1;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
String userId;
String username;
String email;
@Id
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
注意:同一个类中,不可同时使用两种方式。因为两种方式的内部实现方式有所区别。(当然你标注在哪里看你个人爱好了,我比较喜欢标注在字段上面,因为我查找和修改的时候方便一些,我也见很多人标注在属性上面,具体哪种性能上更优秀一些,寡人没具体研究过,的需要查看源码了,并且每种实现产品又不一样,所以一直懒得去看)
建议:当您定义字段时,最好声明为私有的。
因为持久化提供器可能需要覆盖设置器和获取器,所以不能持久化的设置器和获取器声明为final。也就是get和set。
?如果你也随着我说的,自己打并执行了上面的代码,你会发现username和email我们并没有进行任何的标识,也生产了相应的数据库字段,但是如果我们不想生成该怎么办?定义顺时字段:加上@Transsient。也就是有些字段你不想映射进数据库时。
这里我们就简单的说了一下,后面我们会通过其他的解决,顺便解决了这里的详细使用。
2.3指定实体身份
?为什么要有实体身份并且规定是必须进行指定:上面我们介绍了第一个注解@Entity,把POJO声明为实体bean。这是不够的,因为实体在某个时间必须被持久化为数据库表中唯一可表示的行(或多个表中行的集合),如果没有进行标识,你就不知道在执行保存操作之后数据被保持到哪一行了。(我们还需要重写equals方法,是比较两个明显不同数据库记录的主键在对象中的等效方式)
身份表示注解:
a.@Id
b.@IdClass
c.@EmbeddedId
?问题:怎么会有3种注解,我平时用到的仅仅是@Id,我感觉应该学着带着问题和思考去学习一个知识。
?什么样的类型可标识为实体身份:EJB3支持原始类型、原始包装器和Serializable类型(比如java.lang.String、java.util.Date、java.sql.Date)作为身份,此外因为float、Float、double等类型不确定的特点,当选址数据类型时应该避免使用这些类型。
第一种:@Id,相信对jpa有一点点了解的人就会知道这是做什么的,怎么用。
?后两种注解出项的原因:你有时使用一个以上的属性或字段(复合键)唯一的标识实体。
第二种:@IdClass
如:(一般通过例子就完全可以理解的,我就不会多说了)
package cn.partner4java.bean.part2_3;
import java.io.Serializable;
import java.util.Date;
public class CategoryPK implements Serializable {
private String name;
private Date CreateDate;
…hashCode()…equals(Object obj)
package cn.partner4java.bean.part2_3;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
@Entity
@IdClass(CategoryPK.class)
public class Category {
@Id
private String name;
@Id
private Date CreateDate;
private String realname;
}
第三种:@EmbeddedId
package cn.partner4java.bean.part2_3;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Embeddable;
@Embeddable
public class CategoryPK implements Serializable {
private String name;
private Date CreateDate;
。。。
package cn.partner4java.bean.part2_3;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
@Entity
public class Category {
@EmbeddedId
private CategoryPK categoryPK;
private String realname;
}
有些地方说:这里的CategoryPK可以不实现序列化Serializable,但事实是必须也实现。因为所有的字段都必须是序列化的。
这后两种生产复合主键的形式,都可以,看您个人爱好了
2.4 @Embeddable 注解
上面我们第三种方式用到了这个注解进行复合主键对象的声明。它主要用于嵌入对象,我们平时常用的是域对象。如实体关系,一对一。
使用场景:纯粹的面向对象的域建模,所有的域对象总都是可以独立标识的么?如果对象仅仅在其他的对象内部用作方便的数据占位器/组织方式会怎么样?一个常见的例子,是User对象内部使用Address对象,它作为优雅的面向对象的替换方式,替代列出街道地址、城市、邮编等直接作为User对象的字段。因为不太可能在User之外使用Address对象,所以Adress对象没有必要具有身份,这正好是@Embeddable的适用场景。
如:
package cn.partner4java.bean.part1_2_4;
import javax.persistence.Embeddable;
@Embeddable
public class Address {
private String city;
private String state;
private String country;
}
package cn.partner4java.bean.part1_2_4;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
private Long id;
private String username;
@Embedded
private Address address;
}
生成的表仅一个。但是我们如果想生成的是两个表,怎么办呢?是不是有什么属性表示一下?但是我们上面就说过,如果是单独表映射就需要身份表示,否则我们就不知道是对哪个字段进行操作。但是嵌入对象不需要唯一身份。那么就的选择使用实体关系的方式。
3.实体关系
域关系类型和相应注解
关系类型
|
注解
|
一对一
|
@OneToOne
|
一对多
|
@OneToMany
|
多对一
|
@ManyToOne
|
多对多
|
@ManyToMany
|
3.1 @OneToOne
单向一对一:
User对象具有对BillingInfo的引用,但是没有反向引用,换句话说,次关系是单向的。
package cn.partner4java.bean.part1_3_1;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class BillingInfo {
@Id
private Long billingId;
private String bankName;
}
package cn.partner4java.bean.part1_3_1;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class User {
@Id
private String userId;
private String email;
@OneToOne
private BillingInfo billingInfo;
}
在User表里面生成了相应的关系引用字段。
@OneToOne(optional=false)
private BillingInfo billingInfo;
Optional元素:通知持久化提供器相关对象是否必须存在。默认情况下为true,不必存在。
双向一对一:
你需要从关系的任何一端访问相关实体:
package cn.partner4java.bean.part1_3_1;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class BillingInfo {
@Id
private Long billingId;
private String bankName;
@OneToOne(mappedBy="billingInfo",optional=false)
private User user;
}
package cn.partner4java.bean.part1_3_1;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class User {
@Id
private String userId;
private String email;
@OneToOne
private BillingInfo billingInfo;
}
mappedBy=”billingInfo”指定,它通知容器关系的“拥有”端在User类的billingInfo实体变量中,也就是在表User里生产外键引用字段。
Optional参数被设置为false,标识BillingInfo对象不能在没有相关User对象时存在。想想,你如果在User的:
@OneToOne(optional=false)
private BillingInfo billingInfo;
也设置为不能为空,会产生什么后果,保存执行sql语句会产生什么后果?(这个问题留在后面EntityManager使用时解决)
3.2 @OneToMany 和 @ManyToOne
package cn.partner4java.bean.part1_3_2;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Item {
@Id
private Long id;
private String title;
@OneToMany(mappedBy="item")
private Set<Bid> bids;
}
package cn.partner4java.bean.part1_3_2;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Bid {
@Id
private Long bidId;
private Double amount;
@ManyToOne
private Item item;
}
在关系中的非维护端的实体的列上使用mappingBy,从而标记关系的维护端,指定为Bid的item字段为维护端。并且规定必须多的一端为维护端。因为,让世界人名记住小泉的名字,总比让小泉记住世界人民的名字容易的多。
3.3 @ManyToMany
虽然多对多关系可以是单向的,但是由于这种很想特殊、相互独立的性质,所以他们经常是双向的。
package cn.partner4java.bean.part1_3_3;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class CateGory {
@Id
private Long categoryId;
private String name;
@ManyToMany
private Set<Item> items;
}
package cn.partner4java.bean.part1_3_3;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
@Entity
public class Item {
@Id
private Long itemId;
private String title;
@ManyToMany(mappedBy="items")
private Set<CateGory> categories;
}
双向的多对多会单独生成一个表进行关系的维护。
总结:我们上面介绍了各种关系,但是没有详细告诉大家一些注解参数的配置,如改变多对多关系表的名称等等,相信这些还是比较简单的东西,大家可以从文档里面查找。并且下面的第二部分会有详细的介绍。
第二部分:关系对象映射
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。
详细请下载 http://download.csdn.net/source/1995131
分享到:
相关推荐
<bean id="jpaFactoryBean" abstract="true" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dynamicDataSource"/> <!-- Other JPA properties...
http://download.csdn.net/download/vcfriend/10251462 相关学习博文链接: SpringData JPA详解 http://shensuqiao.iteye.com/blog/2096114 W3Cschool JPA概述 https://www.w3cschool.cn/java/jpa-field-mapping.html...
您可以通过运行以下命令启动应用程序:$ ./gradlew bootRun该项目使用kotlin-spring插件来避免在代理类和方法上需要open修饰符,有关更多详细信息,请参见此。 确保您至少具有IntelliJ IDEA 2016.3和Kotlin插件...
7. **Spring Data JPA**:如果选择了相应的起步依赖,项目可能包含了对JPA(Java Persistence API)的支持,允许你方便地与关系型数据库进行交互,如通过 `@Entity` 定义模型,`@Repository` 实现数据访问,`@...
个人博客 https://blog.csdn.net/hykwhjc 第一篇:构建第一个SpringBoot工程] 第二篇:SpringBoot配置详解] 第三篇:SpringBoot日志配置] 第四篇:整合Thymeleaf模板] 第五篇:使用JdbcTemplate访问数据库...
本文将详细介绍JPA的核心概念、基本用法以及如何在实体类中使用JPA注解。 #### 实体类定义 在JPA中,实体类是指代表数据库表的对象模型。为了将一个普通的Java类转变为JPA实体类,我们需要添加一些特定的注解。...
http://download.csdn.net/detail/jincheng52rmb/5349256 http://download.csdn.net/detail/jincheng52rmb/5349247 http://download.csdn.net/detail/jincheng52rmb/5349230 典型模型与项目实战大全>> 出版社: 清华...
后台基于SpringBoot框架,数据库访问同时集成了Jpa与MyBatis-Plus,即可自动生成数据库表结构,又可灵活编写sql。前端基于vue-next-admin/vben框架,引入了bpmn.js工作流、VForm可视化表单。默认前端(Element-Plus...
- chapter1:[基本项目构建(可作为工程脚手架),引入...由于Spring Cloud偏宏观架构,Spring Boot偏微观细节,内容上越来越多,为了两部分内容不互相干扰,所以迁移Spring Cloud内容到:[SpringCloud-Learning项目]...
下面将详细讨论与这个项目相关的JavaWeb技术和知识点。 【描述】提到的"人员信息管理系统"是一个基于Web的应用程序,主要用于存储、管理和检索员工的相关数据。在设计和实现这样一个系统时,开发者通常会运用一系列...
https://download.csdn.net/download/weixin_54626591/85473419 测试图片请访问 https://download.csdn.net/download/weixin_54626591/85473433 前言: 一个简单的外卖系统,包括手机端,后台管理,api 基于spring...
Java Web整合开发王者归来(共4部分含源代码)part2: http://download.csdn.net/detail/tan3739/4595652 Java Web整合开发王者归来(共4部分含源代码)part3: http://download.csdn.net/detail/tan3739/4595610 Java Web...
http://download.csdn.net/source/3275208 Java高手真经 高级编程篇 下载(二) http://download.csdn.net/source/3275230 Java高手真经 高级编程篇 下载(三) http://download.csdn.net/source/3275245 Java...
http://download.csdn.net/source/3275208 Java高手真经 高级编程篇 下载(二) http://download.csdn.net/source/3275230 Java高手真经 高级编程篇 下载(三) http://download.csdn.net/source/3275245 Java...
http://download.csdn.net/source/3275208 Java高手真经 高级编程篇 下载(二) http://download.csdn.net/source/3275230 Java高手真经 高级编程篇 下载(三) http://download.csdn.net/source/3275245 Java...
http://download.csdn.net/source/3275208 Java高手真经 高级编程篇 下载(二) http://download.csdn.net/source/3275230 Java高手真经 高级编程篇 下载(三) http://download.csdn.net/source/3275245 Java...
SpringBoot入门学习主要涵盖SpringBoot的基本概念、核心特性以及如何快速搭建一个运行的Web应用。SpringBoot是由Pivotal团队提供的全新框架,旨在简化Spring应用的初始搭建以及开发过程。它集成了大量的常用第三方库...
数据存储可能使用关系型数据库如MySQL,利用JPA(Java Persistence API)与数据库进行交互,实现数据的CRUD操作。同时,为了保证数据的安全性,系统可能使用Spring Security进行权限控制和认证,确保只有授权的用户...
ELADMIN 网页ELADMIN 前端源码项目源码 资金来源码 前端源码github https://github.com/elunez/eladmin https://github.com/elunez/eladmin-web码云 ...
我们将围绕"dragon_api.rar"这一项目进行详细的分析与讲解。 首先,让我们来看看核心框架——Spring Boot。Spring Boot是由Pivotal团队提供的全新框架,其设计目标是简化Spring应用的初始搭建以及开发过程。它内置...