在之前我们有讲过一节引用传递,当我们了解引用传递后就可以在实际开发中运用到它,那今天我们就来实践一下叭!
1.数据表与简单Java类映射转换
简单Java类是现在面向对象设计的主要分析基础,但对于死机了开发过程中简单Java类的定义来源是有依据的,往往都是根据数据表的机构来实现简单Java类。
在数据库中实际上是有提供若干个数据表的,那么每一张实体数据表实际上都可以描述出一些具体的事物概念,按照这个思路我们来看我们的程序,会发现程序中类的定义形式实际上和这些实体表的差别并不大:
- 数据实体表的设计 = 类的设计
- 表中的字段 = 类的成员属性
- 表的外键关联 = 引用关联
- 表中的一行记录 = 类的一个实例化对象
- 表的多行记录 = 对象数组
上述概念在实例化问题中可以举例为:假设有一个部门,部门中有领导与雇员,雇员有工资、职位、编号等等,那么就会有如下的关联:
- 一个部门有多个雇员
- 一个雇员属于一个部门
- 一个雇员有一个领导’
那么将上述的关系以简单Java类的形式来定义,在整体代码要求可以获取下列信息:
根据部门信息获得以下内容:
- 一个部门的完整信息
- 一个部门中所有雇员的完整信息
- 一个雇员所对应的领导的信息
根据雇员信息可以获得以下内容:
- 一个雇员对应的部门信息
- 一个雇员的领导信息
要做到以上的程度,我们首先编写简单Java类Emp(雇员)类与Dept(部门)类:
class Dept {// 部门类
private long deptno;// 部门编号
private String dname;// 部门名称
private String loc;// 部门位置
public long getDeptno() {
return this.deptno;
}
public void setDeptno(long deptno) {
this.deptno = deptno;
}
public String getDname() {
return this.dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return this.loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public Dept(long deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
public String getInfo() {
return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
}
}
class Emp {// 雇员类
private long empno;// 雇员编号
private String ename;// 雇员姓名
private String job;// 雇员职位
private double sal;// 基本工资
private double comm;// 佣金
public long getEmpno() {
return this.empno;
}
public void setEmpno(long empno) {
this.empno = empno;
}
public String getEname() {
return this.ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public String getJob() {
return this.job;
}
public void setJob(String job) {
this.job = job;
}
public double getSal() {
return this.sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public double getComm() {
return this.comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public Emp(long empno, String ename, String job, double sal, double comm) {
this.empno = empno;
this.ename = ename;
this.job = job;
this.sal = sal;
this.comm = comm;
}
public String getInfo() {
return "Emp [empno=" + empno + ", ename=" + ename + ", job=" + job + ", sal=" + sal + ", comm=" + comm + "]";
}
}
这就是我们的基本信息,这些代码在自己手动编写时可以忽略get(),set()方法,但如果使用工具比如Eclipse,那么一键生成get(),set()方法也是毫不费力,对于基本信息的代码,要多敲多练,在开发中一次编译通过基本代码是一个程序员的基本素养。
接下来我们要处理不同类之间的关联,需要用到我们上次讲的引用传递,雇员与领导的关系、雇员与部门的关系、部门与雇员的关系,分别在Emp类与Dept类中添加下列代码:
雇员与领导、雇员与部门:
private Dept dept;//雇员所在的部门
private Emp mgr;//雇员的领导
public Dept getDept() {
return this.dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public Emp getMgr() {
return this.mgr;
}
public void setMgr(Emp mgr) {
this.mgr = mgr;
}
部门与雇员,注意:部门中的雇员是多个,所以需要使用数组:
private Emp emps [];//部门中的雇员
public Emp[] getEmps() {
return this.emps;
}
public void setEmps(Emp[] emps) {
this.emps = emps;
}
到此为止,我们的基本信息与关系就已经实现的差不多了,但是需要进行开发的时候一定通过两个步骤:
- 根据表的结构关系进行对象的实例化配置
- 根据要求通过结构获取数据
现在我们根据需求来进行实例化对象:
public class first {
public static void main( String args[] ){
//根据关系进行类的定义
Dept dept = new Dept(1, "财务部", "上海");
Emp empA = new Emp(5001L, "紫郡", "CLERK", 3000, 0);
Emp empB = new Emp(4001L, "紫薇五号", "MANAGER", 6000, 500);
Emp empC = new Emp(3001L, "紫薇三号", "PRESIDENT", 8000, 2000);
}
}
然而这些对象现在还没有关联,现在我们来加强关联。继续在代码后添加:
//为对象进行关联设置
empA.setDept(dept);//设置雇员与部门之间的关联
empB.setDept(dept);//设置雇员与部门之间的关联
empC.setDept(dept);//设置雇员与部门之间的关联
empA.setMgr(empB);//设置雇员与领导之间的关联
empB.setMgr(empC);//设置雇员与领导之间的关联
dept.setEmps(new Emps[] {empA, empB, empC});//设置部门与雇员之间的关联
这里需要注意,empC是没有领导的。
接下来,我们要根据需求获取数据,首先根据部门信息来获取:
//根据需求获取数据
System.out.println(dept.getInfo());
for(int i = 0; i < dept.getEmps().length; i++) {
System.out.println("------------------------------------------------"
+ "------------------------------------------------------");
System.out.println("\t|-" + dept.getEmps()[i].getInfo());
if(dept.getEmps()[i].getMgr() != null) {
System.out.println("\t\t|-" + dept.getEmps()[i].getMgr().getInfo());
}
}
上面的代码编译后,运行结果如下:
部门 [部门编号:1, 部门名称:财务部, 部门地址:上海]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:5001, 姓名:紫郡, 职位:CLERK, 工资:3000.0, 佣金:0.0]
|-雇员 [编号:4001, 姓名:紫薇五号, 职位:MANAGER, 工资:6000.0, 佣金:500.0]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:4001, 姓名:紫薇五号, 职位:MANAGER, 工资:6000.0, 佣金:500.0]
|-雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
我们通过部门,获取了部门完整信息,部门中每个雇员的信息,以及每个雇员的领导的信息。
接下来我们通过雇员来获取信息:
System.out.println("------------------------------------------------"
+ "------------------------------------------------------");
System.out.println(empB.getDept().getInfo());
System.out.println(empB.getMgr().getInfo());
代码十分简单,添加在刚才的代码后面就行了,我们以empB为例,来运行这个程序,结果如下:
部门 [部门编号:1, 部门名称:财务部, 部门地址:上海]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:5001, 姓名:紫郡, 职位:CLERK, 工资:3000.0, 佣金:0.0]
|-雇员 [编号:4001, 姓名:紫薇五号, 职位:MANAGER, 工资:6000.0, 佣金:500.0]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:4001, 姓名:紫薇五号, 职位:MANAGER, 工资:6000.0, 佣金:500.0]
|-雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
------------------------------------------------------------------------------------------------------
部门 [部门编号:1, 部门名称:财务部, 部门地址:上海]
雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
可以看到,通过empB,获取了雇员的部门信息,以及雇员的领导信息,这就是一个简单的基本映射转换,大家要知道这种映射转换形式是我们迈向正规开发的第一步。
2.一对多映射
什么是一对多映射,简单来说就是按照表的要求将表的结构转换为类结构,同时可以获取信息。在刚才的例子中,我们通过Dept可以获得以下信息:
- 一个部门的完整信息
- 一个部门中所有雇员的完整信息
- 一个雇员所对应的领导的信息
这就是一个典型的一对多的映射类型:
部门 [部门编号:1, 部门名称:财务部, 部门地址:上海]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:5001, 姓名:紫郡, 职位:CLERK, 工资:3000.0, 佣金:0.0]
|-雇员 [编号:4001, 姓名:紫薇五号, 职位:MANAGER, 工资:6000.0, 佣金:500.0]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:4001, 姓名:紫薇五号, 职位:MANAGER, 工资:6000.0, 佣金:500.0]
|-雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
------------------------------------------------------------------------------------------------------
|-雇员 [编号:3001, 姓名:紫薇三号, 职位:PRESIDENT, 工资:8000.0, 佣金:2000.0]
这部分非常简单,是以后会常用的基础技能,大家一定要熟练掌握并能使用它。
3.多对多映射
与一对多相似,只不过我们可以获取信息的对象变得更多了。举个例子,如果我们创建一个商品类,再创建一个顾客类,那么每个顾客浏览过的商品信息可以通过顾客获得,而每个商品被哪位顾客浏览过的信息就可以通过商品来获得。
首先我们来创建简单Java类:
class Member{
private long id;
private String name;
private Product products [];
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 Product[] getProducts() {
return products;
}
public void setProducts(Product[] products) {
this.products = products;
}
public Member(long id, String name){
this.id = id;
this.name = name;
}
public String getInfo() {
return "Member [id=" + id + ", name=" + name + "]";
}
}
class Product{
private long id;
private String name;
private double price;
private Member members [];
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 double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Member[] getMembers() {
return members;
}
public void setMembers(Member[] members) {
this.members = members;
}
public Product(long id, String name, double price){
this.id = id;
this.name = name;
this.price = price;
}
public String getInfo() {
return "Product [id=" + id + ", name=" + name + ", price=" + price + "]";
}
}
然后我们实例化对象,并根据需求进行关联:
public class first {
public static void main( String args[] ){
//根据关系进行类的定义
Member mA = new Member(1L, "紫薇一号");
Member mB = new Member(2L, "紫薇二号");
Product pA = new Product(1001L, "智能手环", 180);
Product pB = new Product(1002L, "java书籍", 90);
Product pC = new Product(1003L, "智能电视", 3800);
//为对象进行关联设置
mA.setProducts(new Product[] {pA, pC});
mB.setProducts(new Product[] {pA, pB});
pA.setMembers(new Member[] {mA, mB});
pB.setMembers(new Member[] {mB});
pC.setMembers(new Member[] {mA});
//根据需求获取数据
}
}
最后我们获取数据:
//根据需求获取数据
System.out.println("--------------------" + "根据商品获取数据" + "--------------------");
System.out.println(pA.getInfo());
for(int i = 0; i < pA.getMembers().length; i++) {
System.out.println("------------------------------------------------------");
System.out.println("\t|-" + pA.getMembers()[i].getInfo());
}
System.out.println("--------------------" + "根据顾客获取数据" + "--------------------");
System.out.println(mA.getInfo());
for(int i = 0; i < mA.getProducts().length; i++) {
System.out.println("------------------------------------------------------");
System.out.println("\t|-" + mA.getProducts()[i].getInfo());
}
运行上面的代码,结果如下:
--------------------根据商品获取数据--------------------
Product [id=1001, name=智能手环, price=180.0]
------------------------------------------------------
|-Member [id=1, name=紫薇一号]
------------------------------------------------------
|-Member [id=2, name=紫薇二号]
--------------------根据顾客获取数据--------------------
Member [id=1, name=紫薇一号]
------------------------------------------------------
|-Product [id=1001, name=智能手环, price=180.0]
------------------------------------------------------
|-Product [id=1003, name=智能电视, price=3800.0]
可以看到我们通过商品就获取了顾客的信息,也通过顾客就获取了商品的信息,我们还可以在外层再套一个for循环来使所有的商品和用户信息都打印出来。
这就是一个典型的多对多模式,看似与一对多没有什么不同,其实之在生活中就有这样的例子,比如商家与用户,用户在购买商品后商家会接到通知,而用户可以将多个商品加入购物车,这就是一个多对多的映射,如果我们还像一对多那样编写代码,那么用户在购物车中每添加一个商品我们都要在程序中再加一次一对多映射,非常麻烦,多对多就很好的解决了这个问题。
4.复杂多对多映射
我们了解了一对多与多对多映射之后,就能进行简单的数据表与Java类的转换实现。
而在实际生活中不会只有简单的两个类的关联,以上述商家与用户为例:
- 用户与商品是多对多关系
- 而商家只在乎购买过的用户,也就是”顾客“,商家与顾客是一对多关系
- 而用户是否成为顾客,又是多对多关系
这些复杂的关联将我们的生活串联起来,我们在实际开发中需要认识并注意到这些问题。
今天我们在引用传递的基础上,整理了映射转换的知识点,这两个知识点都是以后在开发中会经常用到的,我们要熟练掌握并能使用它们,下次见👋