MyEclipse6Java开发中文教程 @ Temporal:如果属性是时间类型,因为数据表对时间类型有更严格的划分,所以必 须指定具体时间类型。在 Javax, persistence TemporalType枚举中定义了3种时间类型 1)DATE:等于 java. sql Date 2)TME:等于 java. sql.Time; 3) TIMESTAMP:等于java.sq. Timestamp 用法示例 @ Column(name BIRTHDAY @Temporal(Tempora/Type DATE) 。同样的这个标注不是必须的,但是它没有默认值,所以必须指定一个取值。 常用的这些标注基本上已经介绍完毕,那么一个最简单的实体定义代码示例如下 @EI public class Myuser implements java. io Serializable i @ld private Integer id; 。在这种情况下,所有的取值都采用默认值,表名和实体名相对应,而变量名及其类型则和 数据库表的列相对应。所以说标注方式大大简化了JPA的开发 为了不使读者疑惑,我们还必须介绍属性标注的两种位置:标注在属性( property)和标 注在变量(fed上。到底采用那种位置,取决于@d标注出现的位置。而且一旦采用了一种 标注方式后,就不能再混合使用了。例如 @ld @Column private Integer id 这种方式就是fed方式,那么所有其它的列定义都应该标在变量上。 而 @|d @Column Public Integer getlo return. 这样的方式就是属性方式。默认情况下,JPA采用的是属性定义的方式,也就是根据方法来 确定有哪些属性 @ Transient:实体bean中所有的非stac非 transient的属性都可以被持久化,除非 你将其注解为@ Transient。所有没有定义注解的属性等价于在其上面添加了@ Basic注解。 虽然默认情况一般都工作的很好,然而实际开发中有一种情况可能会出现:在实体类中提供 了一个算总帐的方法,但是这个总帐属性却没有和数据库的任何列对应,这时候你就可以通 过@ Transient标注使它不会保存到数据库中,类似的也可以这样来不保存其它的属性到数 据库中。例如 @Transient Public double getTota/Cost(.) 其它可以标在属性上的标注还有 @Lob;表示属性将被持久化为Blob或者Cob类型(大数据类型,例如超过10MB的数据), 具体取决于属性的类型。 java. sql Clob, Character,char和 java. lang String这些类型 的属性都被持久化为Cob类型;而 java. sql Blob,Byte,byte和 Serializable类型则被 刘长炯著
MyEclipse 6 Java 开发中文教程 11 刘长炯著 @Temporal:如果属性是时间类型,因为数据表对时间类型有更严格的划分,所以必 须指定具体时间类型。在 javax.persistence.TemporalType 枚举中定义了 3 种时间类型: 1) DATE :等于 java.sql.Date; 2) TIME :等于 java.sql.Time; 3) TIMESTAMP :等于 java.sql.Timestamp。 用法示例: @Column(name = "BIRTHDAY") @Temporal(TemporalType.DATE) 。同样的这个标注不是必须的,但是它没有默认值,所以必须指定一个取值。 常用的这些标注基本上已经介绍完毕,那么一个最简单的实体定义代码示例如下: @Entity public class Myuser implements java.io.Serializable { @Id private Integer id; …. 。在这种情况下,所有的取值都采用默认值,表名和实体名相对应,而变量名及其类型则和 数据库表的列相对应。所以说标注方式大大简化了 JPA 的开发。 为了不使读者疑惑,我们还必须介绍属性标注的两种位置:标注在属性(property)和标 注在变量(field)上。到底采用那种位置,取决于@Id 标注出现的位置。而且一旦采用了一种 标注方式后,就不能再混合使用了。例如: @Id @Column private Integer id; 这种方式就是 field 方式,那么所有其它的列定义都应该标在变量上。 而: @Id @Column Public Integer getId() { return …} 这样的方式就是属性方式。默认情况下,JPA 采用的是属性定义的方式,也就是根据方法来 确定有哪些属性。 @Transient:实体 bean 中所有的非 static 非 transient 的属性都可以被持久化,除非 你将其注解为@Transient。所有没有定义注解的属性等价于在其上面添加了@Basic 注解。 虽然默认情况一般都工作的很好,然而实际开发中有一种情况可能会出现:在实体类中提供 了一个算总帐的方法,但是这个总帐属性却没有和数据库的任何列对应,这时候你就可以通 过@Transient 标注使它不会保存到数据库中,类似的也可以这样来不保存其它的属性到数 据库中。例如: @Transient Public double getTotalCost() {…} 。 其它可以标在属性上的标注还有: @Lob:表示属性将被持久化为 Blob 或者 Clob 类型(大数据类型,例如超过 10MB 的数据), 具体取决于属性的类型。java.sql.Clob,Character[],char[] 和 java.lang.String 这些类型 的属性都被持久化为 Clob 类型;而 java.sql.Blob,Byte[],byte[] 和 Serializable 类型则被
MyEclipse6Java开发中文教程 持久化为Blob类型。用法示例: @ String maillet @ Basic:刚刚已经提到了@ Basic,它一般可以来控制是否进行延迟价值。用法示例: @ Basic(fetch= FetchType. Lazy)米用延迟加载, FetchType. EAGER一般不采用,它是非 延迟价值模式 关于实体类还有一个话题没有谈,那就是实体类不能像普通的 JavaBean那样随心所欲 的进行编写,它有一些这样的限制 Entity类必须要有一个无参数的pubc或者 protected的 Constructor 如果在应用中需要将该 Entity类分离出来在分布式环境中作为参数传递,该 Entity类 需要实现 Java.Io. Serializable接口。 Entity类不可以是fnal,也不可有fnal的方法。 abstract类和 Concrete实体类都可以作为 Entity类。 Entity类中的属性变量不可以是 public。 Entity类的属性必须通过 getter/setter或者其 他的商业方法获得。 最后,实体类还支持继承,一对一,一对多和多对多,以及命名查询( NamedQuery, 在 Netbeans开发工具生成JPA实体的时候经常可以看到)等标注。实际上 MyEclipse能 够自动生成这样的代码( Netbeans开发工具也可以生成),所以在这里我们略作介绍: 对一映射:双向一对一关系需要在关系维护端( owner side)的one2 l one Annotation 定义 mappedBy属性。建表时在关系被维护端( inverse side)建立外键列指向关系维护端 的主键列 @one ToOne(optional=true, cascade Cascade Type. ALL, mapped By =country) private Capital capital, 对多映射:双向一对多关系,一是关系维护端( owner side),多是关系被维护端 ( inverse side)。建表时在关系被维护端建立外键列指向关系维护端的主键列 DOne ToMany(targetEntity Child class, cascade= Cascade Type. ALL, mappedBy father) public List<Child> getchildren(i return children; 3 多对多映射: 多对多映射采取中间表连接的映射策略,建立的中间表将分别引入两边的主键作为外 键。(比较少用,建议不要用,性能问题严重) 下面则给大家列出一个 NamedQuery的代码片段: @Entity @Table(name="address") @Named Queries(t @Named Query(name= Address. find By Address/d, query="SELECT a FROM Address a WHERE a addressId =address/D") @Named Query(name Address findBy city", query = SELECT a FROM Address a WHERE acity =:city") @Named Query(name = Address. findByStreet, query "SELECT a FROM 刘长炯著
MyEclipse 6 Java 开发中文教程 12 刘长炯著 持久化为 Blob 类型。用法示例: @Lob String mailText; @Basic:刚刚已经提到了@Basic,它一般可以来控制是否进行延迟价值。用法示例: @Basic(fetch=FetchType.Lazy) //采用延迟加载,FetchType.EAGER 一般不采用,它是非 延迟价值模式 关于实体类还有一个话题没有谈,那就是实体类不能像普通的 JavaBean 那样随心所欲 的进行编写,它有一些这样的限制: z Entity 类必须要有一个无参数的 public 或者 protected 的 Constructor。 z 如果在应用中需要将该 Entity 类分离出来在分布式环境中作为参数传递,该 Entity 类 需要实现 java.io.Serialzable 接口。 z Entity 类不可以是 final,也不可有 final 的方法。 z abstract 类和 Concrete 实体类都可以作为 Entity 类。 z Entity 类中的属性变量不可以是 public。Entity 类的属性必须通过 getter/setter 或者其 他的商业方法获得。 最后,实体类还支持继承,一对一,一对多和多对多,以及命名查询(NamedQuery, 在 Netbeans 开发工具生成 JPA 实体的时候经常可以看到)等标注。实际上 MyEclipse 能 够自动生成这样的代码(Netbeans 开发工具也可以生成),所以在这里我们略作介绍: 一对一映射:双向一对一关系需要在关系维护端(owner side)的 one2one Annotition 定义 mappedBy 属性。建表时在关系被维护端(inverse side)建立外键列指向关系维护端 的主键列。 @OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "country") private Capital capital; 一对多映射:双向一对多关系,一是关系维护端(owner side),多是关系被维护端 (inverse side)。 建表时在关系被维护端建立外键列指向关系维护端的主键列。 @OneToMany(targetEntity = Child.class, cascade = CascadeType.ALL, mappedBy = "father") public List<Child> getChildren() { return children; } 多对多映射: 多对多映射采取中间表连接的映射策略,建立的中间表将分别引入两边的主键作为外 键。(比较少用, 建议不要用, 性能问题严重) 下面则给大家列出一个 NamedQuery 的代码片段: @Entity @Table(name = "address") @NamedQueries( { @NamedQuery(name = "Address.findByAddressID", query = "SELECT a FROM Address a WHERE a.addressID = :addressID"), @NamedQuery(name = "Address.findByCity", query = "SELECT a FROM Address a WHERE a.city = :city"), @NamedQuery(name = "Address.findByStreet", query = "SELECT a FROM
MyEclipse6Java开发中文教程 Address a WHERE astreet =. street @Named Query(name =" Address. findByzip, query "SELECT a FROM Address a WHERE a zip = zip) public class Address implements Serializable 131.34使用 Entity Manager来管理实体 这样,我们关于实体类的标注的介绍暂告一段落,接下来我们说以下如何编写DAO, 换句话就是如何进行增删改查这样的持久化操作。之所以介绍是因为 MyEclipse生成的代码 中也包含了这些由基本内容 合起来的代码,读者阅读后可以对这有深入的了解,便于 自己修改代码。要操作实体类,就必须接触下面所说的几个类: Persistence, Entity ManagerFactory和 EntityManager。它们的相互关系如图134所示 Persistence EntityManagerFactory EntityManager 创建 实体容器 ∴管理 实体1 实体2 图134实体管理器的创建经过 cSF PERSISTENCE PRDVIDER: String nonCommentPattern Pattern o createEntityMManagerFactory (String): Entit os createEntityMl anager Factory(String, Map. 曰° findAllProvi ders o:void a providerNamesFromReader (BufferedReader) I EntityManagerFactory o createEntityMlanager 0: EntityManager ● close:void e isOpen: boolean 刘长炯著
MyEclipse 6 Java 开发中文教程 13 刘长炯著 Address a WHERE a.street = :street"), @NamedQuery(name = "Address.findByZip", query = "SELECT a FROM Address a WHERE a.zip = :zip") }) public class Address implements Serializable { 13.1.3.4 使用 EntityManager 来管理实体 这样,我们关于实体类的标注的介绍暂告一段落,接下来我们说以下如何编写 DAO, 换句话就是如何进行增删改查这样的持久化操作。之所以介绍是因为 MyEclipse 生成的代码 中也包含了这些由基本内容一一组合起来的代码,读者阅读后可以对这有深入的了解,便于 自己修改代码。要操作实体类,就必须接触下面所说的几个类: Persistence , EntityManagerFactory 和 EntityManager。它们的相互关系如图 13.4 所示。 图 13.4 实体管理器的创建经过
MyEclipse6Java开发中文教程 o find (Class<T>, Object)<T> rEference(Class <t> Object) <T> ●ushO:void o setFlushMode (FlushModeType): void o getFlushModeo: FlushModeType lock(Object, LocHModeType) o clear: void o contains ( Object): boolean o createQuery (String): Query o createNamedquery (String): Query o createNativeQuery (String):Query o createNativeQuery (String, Class): Query o createNativeQuery (String, String):Query Transaction O close: void ●is0penO: boolean getTransaction(: EntityTransaction 图135PA实体工厂类图 那么这几个类之间有何关系呢?在独立运行的模式下,EJB3定义了一个 avax persistence Persistence i类用于启动EB3运行环境。只有 Entity Manager是最后 和实体打交道的对象,包括保存,更新,删除和查询等等操作,而要获得Ent! Manager, 首先需要通过 Persistence类调用其 create EntityManagerFactory方法获得 Entity ManagerFactory,然后调用 EntityManagerFactory的 createEntity Manager(方法获 得。我们可以认为, Persistence相当于JDBC的驱动类, EntityManagerFactory则相当 于连接工厂,而 Entity Manager则最后和特定的数据库建立连接并互相操作。下面是一段示 例代码 EntityManagerFactory emf Persistence createEntityManagerFactory (JPADemoPU EntityManager entityManager emf create Entity Manager( 当调用 Persistence. createEntityManagerFactory(的时候, Persistence会是否存在 META- INF/persistence.xml配置文件,然后根据此文件再来初始化 EntityManagerFactory 从图135中可以看到 Persistence和 EntityManagerFactory都是相当简单的类,它们之间 的关系就是一个创建与被创建的工厂模式(就跟拖拉机厂造拖拉机一样)。 Persistence类的 createEntityManagerFactory()方法有两个参数:必选的持久化单元名称( String类型) 和可选的额外属性设置(Map类型)。同样的 EntityManagerFactory中的 createEntityManager0方法也可以带一个可选的额外属性设置参数(Map类型)。 另外在容器环境下(一般是位于EJB服务器中,后面的EJB章节中会加以介绍),创 建 Entity ManagerFactory或者 EntityManager可以不用通过 Persistence来进行,而使用标 注即可,一般其代码如下所示 @Persistence Context EntityManager em, @Persistence Unit 刘长炯著
MyEclipse 6 Java 开发中文教程 14 刘长炯著 图 13.5 JPA 实体工厂类图 那么这几个类之间有何关系呢?在独立运行的模式下, EJB3 定义了一个 javax.persistence.Persistence 类用于启动 EJB3 运行环境。只有 EntityManager 才是最后 和实体打交道的对象,包括保存,更新,删除和查询等等操作,而要获得 EntityManager, 首先需要通过 Persistence 类调用其 createEntityManagerFactory() 方法获得 EntityManagerFactory,然后调用 EntityManagerFactory 的 createEntityManager()方法获 得。 我们可以认为,Persistence 相当于 JDBC 的驱动类,EntityManagerFactory 则相当 于连接工厂,而 EntityManager 则最后和特定的数据库建立连接并互相操作。下面是一段示 例代码: EntityManagerFactory emf = Persistence.createEntityManagerFactory(“JPADemoPU”); EntityManager entityManager = emf.createEntityManager(); 当调用 Persistence.createEntityManagerFactory()的时候,Persistence 会是否存在 META-INF/persistence.xml 配置文件,然后根据此文件再来初始化 EntityManagerFactory。 从图 13.5 中可以看到 Persistence 和 EntityManagerFactory 都是相当简单的类,它们之间 的关系就是一个创建与被创建的工厂模式(就跟拖拉机厂造拖拉机一样)。Persistence 类的 createEntityManagerFactory()方法有两个参数:必选的持久化单元名称(String 类型) 和可选的额外属性设置( Map 类 型 )。 同 样 的 EntityManagerFactory 中 的 createEntityManager()方法也可以带一个可选的额外属性设置参数(Map 类型)。 另外在容器环境下(一般是位于 EJB 服务器中,后面的 EJB 章节中会加以介绍),创 建 EntityManagerFactory 或者 EntityManager 可以不用通过 Persistence 来进行,而使用标 注即可,一般其代码如下所示: @PersistenceContext EntityManager em; @PersistenceUnit
MyEclipse6Java开发中文教程 Entity ManagerFactory emf 。前面已经讲过,标注仅仅是一个标签而已,一定要有容器来处理这个标签,这些值才能被 设置进去,之后就可以直接使用变量来进行操作了。 在介绍Ent! Manager之前,我们需要了解以下实体的生命周期这个概念。我们知道实 体像人一样,具有出生,学习,服务,死亡等状态,对实体来说,它们的状态规定为: 1.新实体(new 2.持久化实体( managed) 3.分离的实体( detached) 4.删除的实体( removed) 而通过 Entity Manager,可以在它们的不同状态之间实现切换。我们可以简单的通过下表来 确定一个实体的状态 状态名 作为Java对象存在在实体管理器中存在|在数据库中存在 managed √√ detached 而在图136中则列出了状态改变和 Entity Manager之间的关系。图中的em表示实体管理 器( Entity Manager),而ⅸ则表示 Entity Transaction,实体事务管理器。和 Hibernate一样 对实体类的某些操作必须在事务中进行才能成功,这也是本章后面的内容介绍为什么要使用 Spring来整合JPA的一个重要原因。 eh. refresh New em.persisto-Managedtx commit -( Detached emclear em finder query em merge em remove Removed 图136实体状态转换关系图 有了 EntityManager之后,我们就可以像在 Hibernate的seon对象中所做的那样, 对实体进行各种各样的操作了,包括增删改查,刷新,根据主键查找对象等等。图135列 出了 Entity Manager所具有的一些方法,而这些方法的大部分都是和 Hibernate中的 Session 对象很相似的,毕竟所有的ORM都是实现增删改查嘛。我们介绍一些主要的方法 · persist(object)-使实体类从new状态或者 removed转变到 managed状态,并将数 据保存到底层数据库中 remove( Object)-将实体变为 removed状态,当实体管理器关闭或者刷新时,会真正 的删除数据 fnd( Class entity Class, Object key)-以主键查询实体对象, entity Class是实体的类 key是主键值 ● flush0-将实体和底层的数据库进行同步,当我们调用 persist(), merge()或 刘长炯著
MyEclipse 6 Java 开发中文教程 15 刘长炯著 EntityManagerFactory emf; 。前面已经讲过,标注仅仅是一个标签而已,一定要有容器来处理这个标签,这些值才能被 设置进去,之后就可以直接使用变量来进行操作了。 在介绍 EntityManager 之前,我们需要了解以下实体的生命周期这个概念。我们知道实 体像人一样,具有出生,学习,服务,死亡等状态,对实体来说,它们的状态规定为: 1. 新实体(new) 2. 持久化实体(managed) 3. 分离的实体(detached) 4. 删除的实体(removed) 而通过 EntityManager,可以在它们的不同状态之间实现切换。我们可以简单的通过下表来 确定一个实体的状态: 状态名 作为 Java 对象存在 在实体管理器中存在 在数据库中存在 new √ × × managed √ √ √ detached × × √ removed √ √ × 而在图 13.6 中则列出了状态改变和 EntityManager 之间的关系。图中的 em 表示实体管理 器(EntityManager),而 tx 则表示 EntityTransaction,实体事务管理器。和 Hibernate 一样, 对实体类的某些操作必须在事务中进行才能成功,这也是本章后面的内容介绍为什么要使用 Spring 来整合 JPA 的一个重要原因。 图 13.6 实体状态转换关系图 有了 EntityManager 之后,我们就可以像在 Hibernate 的 Session 对象中所做的那样, 对实体进行各种各样的操作了,包括增删改查,刷新,根据主键查找对象等等。图 13.5 列 出了EntityManager所具有的一些方法,而这些方法的大部分都是和Hibernate中的Session 对象很相似的,毕竟所有的 ORM 都是实现增删改查嘛。我们介绍一些主要的方法: z persist(Object) – 使实体类从 new 状态或者 removed 转变到 managed 状态,并将数 据保存到底层数据库中。 z remove(Object) – 将实体变为 removed 状态,当实体管理器关闭或者刷新时,会真正 的删除数据 z find(Class entityClass, Object key) – 以主键查询实体对象,entityClass 是实体的类, key 是主键值 z flush() – 将实体和底层的数据库进行同步,当我们调用 persist( ), merge( )或