jpa学习(个人整理,非转帖)详细请下载 http://download.youkuaiyun.com/source/1995131

本文深入探讨了Java持久化API (JPA) 在域模型中的应用,包括实体定义、复合主键设置及实体间关系建立等内容。

第一部分:实现域模型

1.一些基本理论

域模型是和持久化是密不可分的概念。通常,开发企业项目的第一个步大都就是创建域模型,即列出域中的实体并且定义实体之间的关系。(当然这基本说的是领域建模,好多公司的项目还是采用的数据库建模的形式。)

1.1域模型的相关概念

域模型的四个参与者:对象、关系、关系多样性和关系的可选性。

1》  对象

java对象一样,域模型可以同时具有行为(在java在的方法)和状态(java的实体变量)

2》  关系

java角度来看,关系表现为一个对象引用另一个对象。

充血域模型与贫血域模型

域模型实际上被持久化到数据库中,数据库建模经常和域建模是同义的,域对象包含属性(映射到数据库表的列)而非行为,这种类型的建模被称为贫血模型。

充血模型封装对象的属性、行为,并且利用面向对象实用程序设计方法。(比如继承、多态和封装)。域模型充血度越高,就越难以映射到数据库。

1.2 Ejb3 java持久化API

         Ejb3java持久化API是元数据驱动的pojo技术。也就是说,为了把java对象中的数据保持到数据库中,我们的对象不必实现接口、扩展类,或采用框架模式。

(简单的java对象实际就是普通的javabean是使用pojo名称是为了避免和ejb混淆起来)

声明:如果你熟悉sqljdbc并且喜欢通过自己动手的便利方式得到控制权和灵活性,那么O/R的成熟、技巧和自动化形式可能不适合你。如果情况是这样,那么你应该多了解Spinrg JdbcTemplate(这个我不喜欢用)和iBATIS(这个框架应该对你对对象的理解要求低很多)。可是我要警告您,java本身就是对象化的语言,我们要完美化,就要一切为对象。

2.使用JPA实现域对象    

本章意在描述域对象的实现过程,下一张将详细介绍如何使用对象-关系映射把我们创建的实体和关系映射到数据库中。

(当然现在JPA不仅仅是EJB3值得骄傲的地方,其它好多公司也相继实现了JPA规范,做出了很多优秀的orm框架。如:hibernateopenjpatoplink等。并且规范的好处就在于,你只要完全按照规范来写代码,这些框架你可以随意更换,并是不更改代码的前提下。)

书签:下面我们主要说的是如何定义一个实体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映射被称为基于字段的访问,也就是注解标注在字段上面。当然基于字段如果你省略了getset,也可以生产成功。

如:

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。也就是getset

?如果你也随着我说的,自己打并执行了上面的代码,你会发现usernameemail我们并没有进行任何的标识,也生产了相应的数据库字段,但是如果我们不想生成该怎么办?定义顺时字段:加上@Transsient。也就是有些字段你不想映射进数据库时。

这里我们就简单的说了一下,后面我们会通过其他的解决,顺便解决了这里的详细使用。

2.3指定实体身份

?为什么要有实体身份并且规定是必须进行指定:上面我们介绍了第一个注解@Entity,把POJO声明为实体bean。这是不够的,因为实体在某个时间必须被持久化为数据库表中唯一可表示的行(或多个表中行的集合),如果没有进行标识,你就不知道在执行保存操作之后数据被保持到哪一行了。(我们还需要重写equals方法,是比较两个明显不同数据库记录的主键在对象中的等效方式)

身份表示注解:

a@Id

b@IdClass

c@EmbeddedId

?问题:怎么会有3种注解,我平时用到的仅仅是@Id,我感觉应该学着带着问题和思考去学习一个知识。

?什么样的类型可标识为实体身份:EJB3支持原始类型、原始包装器和Serializable类型(比如java.lang.Stringjava.util.Datejava.sql.Date)作为身份,此外因为floatFloatdouble等类型不确定的特点,当选址数据类型时应该避免使用这些类型。

第一种:@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,从而标记关系的维护端,指定为Biditem字段为维护端。并且规定必须多的一端为维护端。因为,让世界人名记住小泉的名字,总比让小泉记住世界人民的名字容易的多。

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.youkuaiyun.com/source/1995131

node.js Windowv 上安装Node.js Windows 安装包(.msi) : 32 位安装包下载地址 : http://nodejs.org/dist/v0.10.26/node-v0.10.26-x86.msi 64 位安装包下载地址 : http://nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi 安装步骤: 步骤 1 : 双击下载后的安装包 node-v0.10.26-x86.msi,如下所示: install-node-msi-version-on-windows-step1 步骤 2 : 点击以上的Run(运行),将出现如下界面: install-node-msi-version-on-windows-step2 步骤 3 : 勾选接受协议选项,点击 next(下一步) 按钮 : install-node-msi-version-on-windows-step3 步骤 4 : Node.js默认安装目录为 "C:\Program Files\nodejs\" , 你可以修改目录,并点击 next(下一步): install-node-msi-ve rsion-on-windows-step4 步骤 5 : 点击树形图标来选择你需要的安装模式 , 然后点击下一步 next(下一步) install-node-msi-version-on-windows-step5 步骤 6 :点击 Install(安装) 开始安装Node.js。你也可以点击 Back(返回)来修改先前的配置。 然后并点击 next(下一步): install-node-msi-version-on-windows-step6 安装过程: install-node-msi-version-on-windows-step7 点击 Finish(完成)按钮退出安装向导。 install-node-msi-version-on-windows-step8 检测PATH环境变量是否配置了Node.js,点击开始=》运行=》输入"cmd" => 输入命令"path",输出如下结果: PATH=C:\oraclexe\app\oracle\product\10.2.0\server\bin;C:\Windows\system32; C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\; c:\python32\python;C:\MinGW\bin;C:\Program Files\GTK2-Runtime\lib; C:\Program Files\MySQL\MySQL Server 5.5\bin;C:\Program Files\nodejs\; C:\Users\rg\AppData\Roaming\npm 我们可以看到环境变量中已经包含了C:\Program Files\nodejs\ 检查Node.js版本 node-version-test Windows 二进制文件 (.exe)安装 : 32 位安装包下载地址 : http://nodejs.org/dist/v0.10.26/node.exe 64 位安装包下载地址 : http://nodejs.org/dist/v0.10.26/x64/node.exe 安装步骤 步骤 1 : 双击下载的安装包 Node.exe ,将出现如下界面 : install-node-exe-on-windows-step1 点击 Run(运行)按钮将出现命令行窗口: install-node-exe-on-windows-step21 版本测试 进入 node.exe 所在的目录,如下所示: node-version 如果你获得以上输出结果,说明你已经成功安装了Node.js。 Linux上安装 Node.js Ubuntu 源码安装 以下部分我们将介绍在Ubuntu Linux下安装 Node.js 。 其他的Linux系统,如Centos等类似如下安装步骤。 在 Github 上获取 Node.js 源码: install-node-msi-version-on-linux-step1 install-node-msi-version-on-linux-step2 在完成下载后,将源码包名改为 'node'。 install-node-msi-version-on-linux-step3 修改目录权限: install-node-msi-version-on-linux-step4 使用 './configure' 创建编译文件。 install-node-msi-version-on-linux-step5 编译: make。 install-node-msi-version-on-linux-step6 完成安装: make install。 install-node-msi-version-on-linux-step7 最后我们输入'node --version' 命令来查看Node.js是否安装成功。 install-node-msi-version-on-linux-step8 Ubuntu apt-get命令安装 命令格式如下: sudo apt-get install nodejs sudo apt-get install npm centOS下安装nodejs 1、下载源码,你需要在http://nodejs.org/下载最新的Nodejs版本,本文以v0.10.24为例: cd /usr/local/src/ wget http://nodejs.org/dist/v0.10.24/node-v0.10.24.tar.gz 2、解压源码 tar zxvf node-v0.10.24.tar.gz 3、 编译安装 cd node-v0.10.24 ./configure --prefix=/usr/local/node/0.10.24 make make install 4、 配置NODE_HOME,进入profile编辑环境变量 vim /etc/profile 设置nodejs环境变量,在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL 一行的上面添加如下内容: #set for nodejs export NODE_HOME=/usr/local/node/0.10.24 export PATH=$NODE_HOME/bin:$PATH :wq保存并退出,编译/etc/profile 使配置生效 source /etc/profile 验证是否安装配置成功 node -v 输出 v0.10.24 表示配置成功 npm模块安装路径 /usr/local/node/0.10.24/lib/node_modules/ 注:Nodejs 官网提供了编译好的Linux二进制包,你也可以下载下来直接应用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值