实体Bean: 持久化是位于JDBC之上的一个更高层抽象。持久层将对象映射到数据库,以便在查询、、装载、更新或删除对象的时候,无须使用想JDBC那样繁琐的API,在EJB的早期版本中,持久化是EJB平台的一部分。从EJB3.0开始,持久化已经自成规范,被称为Java Persistence API。 Java Persistence API定一个了一种方法,可以将常规的普通Java对象(POJO)映射到数据库,这些普通Java对象被称作entity bean。除了是用Java Persistence 元数据将其映射到数据库外,entity bean与其他Java类没有任何区别。事实上,创建一个Entity Bean对象相当与新建一条记录,删除一个Entity Bean会同时从数据库中删除对应记录,修改一个Entity Bean,容器会自动将Entity Bean的状态同步到数据库。 Java Perisitence API还定义了一种查询语言(JPQL),具有与SQL相类似的特征,只不过做了裁剪,以便处理Java对象而非原始的关系scheme。 根据持久化规范的要求,以下部署描述文件是必须提供的,如果不提供这一文件,则持久化单元也将不存在,因此应用也不能够获得和使得EntityManager。我们需要将这一文件存放在虾类个类文件的META—INF目录下。 Persistence.xml文件指定实体Bean使用的数据源及EntityManager的默认行为。如下: <?xml version=”1.0 ”?> <persistence xmlns=http://java.sun.com/xml/ns/persistence Xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance Xsi:schemaLocation=”http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd” version=”1.0”> <persistence-unit name=”foshanshop” transaction-type=”JTA”> <jta-data-source>java:/DefaultMySqlDS</jta-data-source> <properties> <!—下面属性只是这对Jboss服务器-- > <property name=”hibernate.hbm2ddl.auto”value=”create-dorp”> </property> <!—调整JDBC抓去数量的大小:Statement.setFetchSize()--> <property name=”hibernate.jdbc.fetch_size” value=“”18/> <!—调整JDBC批量更新数量-- > <property name=”hibernate.jdbc.batch_size” value=”10”/> <!—显示最终执行的SQL-- > <property name=”hibernate.format_sql” value=”true”/> </properties> </persistence-unit> </persistence> •Persistence-unit节点可以有一个或多个,每个persistence-unit借点定义了持久化内容名称,使用的数据源及持久化产品专有属性。 •Name 属性定义了persistence-unit的名称,该属性是必须的。设置为数据库的名称 •Transaction-type属性指定了persistence unit是受JTA事物管理并与之集成。还是 使用RESOURCE LOCAL的javax.persistence.EntityTransactionAPI来管理EntityManager实例的事物完整性。此属性在JavaEE环境中默认值是JTA,而在JavaSE环境中则为RESUOURCE_LOCAL。如果transaction-type=”JTA”,你可以使用<jta-data-source>指定数据源的JNDI名称。Jboss数据源的JNDI名称在局部名称空间。因此数据源名称前大小写铭感。 到此。我们知道persistence-unit将固定数量的一组类映射到数据库。 • 在MySql创建数据库时,必须指定数据库的字符集编码为GBK,否则当插入中文字符时会报:Data too long for column。 可以使用下面的SQL创建数据库: CREATE DATABASE ‘FOSHANSHOP’ DEFAULT CHARSET = GBK • 成员属性映射: 默认情况下,实体Bean的全部成员属性都会成为持久化字段。如果不希望一些成员属性成为持久化字段,可以使用@Transient注释标注。如: Public class Person implements Serializable{ …… @Transient Public String getFristName(){ return “xiaoling”;} } 如果你需要将枚举类型成员映射到数据库,可以使用@Enumerated注释进行标注。枚举类型成员属性可以被映射为字段窜形式(用EnumType.STRING指定),也可以映射为枚举值的数据序号(用EnumType.ORDINAL指定)。如下: Public enum CommentType{ NEWS{ public String getName(){return “资讯评论“;}}; PRODUCT{ public String getName(){return “产品评论”;}}; Public abstract String getName(); } @Entity Public class CommentContent implements Serializable{ …… Private CommentType type; //评论类型 @Enumerated(EnumType.STRING) Public CommentType getType(){ return type;} Public void setType (CommentType type){ this.type=type;} } 存放文件或大文本数据进数据库,JDBC使用java.sql.Blob类型存放二进制数据,java.sql.Clob类型存放字符数据。这些数据都非常占内存,@Lob注释作映射这些大数据类型,当属性的类型为byte[],Byte[]或java.io.Serializable时,@Lob注释将映射为数据库的Blob类型,当属性的类型为char[],Character[]或java.lang.String时,@Lob注释将映射为数据库Clob类型。在做内容管理系统时,我们通常会使用大文本数据,这时就有必要在字段或属性的getter方法标注@Lob. @Entity Public class News implements Serializable{ …… Private String content; @Lob Public String getContent(){ return content;} } 对于加了@Lob注释的大数据类型,为了避免每次加载实体时占用大量内存,我们有必要对该属性进行延迟加载,这是我们需要用到@Basic注释。其定义如下: Public @interface Basic{ FetchType fetch() default EAGER; //指定是否延迟加载,默认为立即加载 Boolean operational() default true; //生成数据库结构时字段是否允许为空 } @Entity Public class News implements Serializable{ …… Private String content; @Lob @Basic(fetch=FetchType.LAZY) Public String getContent(){ return content;} } 因为数据表对时间类型有更严格的划分,所以必须使用@Temporal注释指明java.util.Data或java.util.Calender类型的成员属性映射到数据库date、time和timestame中那种类型。注释的定义如下: Package javax.persistence; Public enum TemporatType{ DATE,TIME,TIMESTAMP } @Entity Public class person implements Serializable{ …… Private Date birthday; @Temporal(value=TemporalType.DATE) Public Date getBirthday(){ return birthday;} } 如果你不想将整个MyInfo对象映射进数据库,而只是想把MyInfo中的成员属性映射到数据库,你需要使用@Embedded注释。如: @Entity Public classs Prson Implemenst Serializable{ ...... @Embedded Public MyInfo getInfo(){ return info ;} } //另外还可以通过@javax.persistence.AttributeOverride注释重载MyInfo的成员属性的映射信息。如: @Entity Public class Person implements Serializable{ … @Embedded @AttributeOverride(name=”content”,column=@Column(length=1000)) Public MyInfo getInfo(){ return info ;} } //如果需要重载多个成员属性,可以和@javax.persistence.AttributeOverrides注释配合使用,如: @Entity Public class Person implements Serializable{ …… @Embedded @AttributeOverrides({ @AttirbuteOverride(name=”content”,column=@Column(length=100)), @AttirbuteOverride(name=”xxx”,column=@Column(length=10))}) Public MyInfo getInfo(){ return info; } } 持久化实体管理器EntityManager: 在Java persistence 规范中,EntityManager是为所有持久化操作提供服务的中枢(shu)。实体作为普通Java对象,只有在调用EntityManager将其持久化后,才会变成持久对象。EntityManager在一组固定的实体类与底层数据源之间进行O/R映射的管理,它可以用来添加/删除/更新实体Bean,通过主键查找实体bean,也可以通过JPQL语言查找满足条件的实体Bean。当EntityManager被注入到EJB时,EJB容器会对EntityManager所依赖的持久上下文(persistence context)具有完全的控制权。 持久化上下文(persistence context) 持久化上下文是有一组受托管(attached)的实体对象实例所构成的集合。它受EntityManager的管理。EntityManager跟踪persistence context 中所有对象的修改和更新情况,并根据指定的flush模式将这些修改保存到数据库中。一旦persistence context被关闭,所有实体对象都会脱离EntityManager而成为游离detached对象。对象一旦从persistence context中脱离,就不再受EntityManager管理了,任何对此对象的状态变更也不会被同步到数据库。Java persistence 中有两种类型的persistence context,分别是transaction-scoped 和extended persistence contexts。 实体对象拥有4中状态,这些状态通过调用EntityManager接口方法发生迁移: •新建状态:该对象尚未拥有持久化主键,没有和一个持久化上下文关联。 •托管状态:已经拥有持久化主键并和持久化上下文建立了联系。 •游离状态:【detached】拥有持久化主键,但尚未和持久化上下文建立联系。 •删除状态:拥有持久化主键,已经和持久化上下文建立联系,但已经被安排从数据库中删除。