1 / 29

Java Persistence API(1.0)

Java Persistence API(1.0). 徐克平 2010/4. 概述. Java Persistence API 作为 JavaEE5.0 平台标准的 ORM 规范,将得到所有 JavaEE 服务器的支持。 JPA 由 EJB3.0 软件开发组开发,作为 JSR-220 实现的一部分。 目前 Hibernate3.2 、 TopLink10.1.3 以及 OpenJPA 都提供了 JPA 的支持。. 什么是 JPA. JPA 包括以下三个方面技术

Download Presentation

Java Persistence API(1.0)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java Persistence API(1.0) 徐克平 2010/4

  2. 概述 • Java Persistence API作为JavaEE5.0平台标准的ORM规范,将得到所有JavaEE服务器的支持。 • JPA由EJB3.0软件开发组开发,作为JSR-220实现的一部分。 • 目前Hibernate3.2、TopLink10.1.3以及OpenJPA都提供了JPA的支持。

  3. 什么是JPA JPA包括以下三个方面技术 • ORM映射元数据,JPA支持xml和jdk5.0注释,元数据描述对象与表之间的映射关系,框架据此将实体对象持久化到数据库当中。 • Java持久化API,用来操作实体对象,执行CURD操作,框架在后台替我们完成所有的事情开发者可以从JDBC和SQL代码中解脱出来。 • 查询语言,这是持久化操作很重要的一个方面,通过面向对象而非面向数据库的查询数据,避免程序与SQL的紧密耦合。

  4. 环境构建 • Ide采用MyEclipse6.0,数据库采用Mysql,持久层框架JPA1.0。 • Hibernate 从3.2开始,就开始兼容JPA。Hibernate3.2获得了Sun TCK的JPA(Java Persistence API) 兼容认证。 • 下载地址http://www.hibernate.org/当中的3.2版本。

  5. 开发JPA依赖的jar包开发JPA依赖的jar包 Hiberante核心包(8个文件) hibernate-distribution.GA --------------------------------------------- hibernate3.jar lib\bytecode\cglib\hibernate-cglib-repack.jar lib\required\*.jar Hiberante注解包(3个文件):hibernate-annotationsGA ------------------------------------------------------------------------------------ hibernate-annotations.jar lib\ejb3-persistence.jar、hibernate-commons-annotations.jar Hibernate针对JPA的实现包(3个文件):hibernate-entitymanagerGA ------------------------------------------------------------------------------------------------------ hibernate-entitymanager.jar lib\test\log4j.jar、slf4j-log4j12.jar

  6. JPA配置文件 JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的,模版如下: <?xml version="1.0" encoding="UTF-8"?> <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/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"version="1.0"> <persistence-unit name="jpaPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.connection.driver_class"value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url“ value="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8" /> <property name="hibernate.connection.username" value="root" /> <property name="hibernate.connection.password" value="root" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit> </persistence>

  7. 实体对象 • 访问数据库之前,我们总是要设计在应用层承载数据数据的领域对象,ORM框架将它们持久化到数据库当中。 • 按照JPA规范实体必须具备以下要求: 必须使用javax.persistence.Entity注解或者在XML映射文件中有对应的元素。 必须具有一个不带参的构造函数,类不能声明final,方法和持久化的属性也不能声明成final。并且持久化的属性修饰符不能为public。 如果游离状的实体需要以值的方式进行传递,如Session bean,则必须实现Serializable接口

  8. 使用基本注解元数据 • @Entity:将领域对象标注为一个实体,默认情况下类名为表名,通过name可以重新指定。 • @Id:属性对应的表的主键。 • @Column:属性对应的表字段。 • @GeneratedValue:主键产生策略,通过startage属性指定。

  9. 主键生成策略 • IDENTITY:主键由数据库自动生成。 • AUTO:JPA自动选择合适的策略,是默认选项。 • SEQUENCE:通过序列产生主键,条件是数据库需要支持序列。 • TABLE:通过表产生主键,使用该策略更易于数据库移植。

  10. 实体关系 • 实体之间的关系有:一对一,一对多,多一对,多对多。关系是多态的。 • 双向关系的反向端必须通过OnToOne,OnToMany或ManyToMany注解的MappedBy元素指向它的持久端。MappedBy表示主控端的属性/字段。 • 一对多/多对一双向关系中的多端必须是持久端,因此不能再ManyToOne中使用MappedBy元素。 • 对于一对一双向关系,包括对应的外键(foreign for)的那一端是持久端。 • 对于多对多双向关系,任何一端都是持久端。

  11. 双向OnToOne关系 @Entity public class Employee { private Cubicle cubicle; @OneToOne public Cubicle getCubicle() { return cubicle; } } @Entity public class Cubicle { private Employee employee; @OneToOne(mappedBy = "cubicle") public Employee getEmployee( ) { return employee; } }

  12. 双向ManyToOne/OnToMany! • @Entity • public class Employee { • private Department department; • @ManyToOne • public Department getDepartment() { • return department; • } • public void setDepartment(Department department) { • this.department = department; • } • ... • } 非常简单

  13. 双向ManyToOne/OnToMany! • @ • Entity • public class Department { • private Collection<Employee> employees = new HashSet(); • @OneToMany(mappedBy="department") • public Collection<Employee> getEmployees() { • return employees; • } • public void setEmployees(Collection<Employee> employees) { • this.employees = employees; • } • ... • }在这个例子中: • 实体Employee引用实体Department的单个实例。 • 实体Department引用一个实体Employee的集合

  14. 单向一对一! • @Entity • public class Employee { • private TravelProfile profile; • @OneToOne • public TravelProfile getProfile() { • return profile; • } • public void setProfile(TravelProfile profile) { • this.profile = profile; • } • ... • }

  15. 单向一对一! • @Entity • public class TravelProfile { • ... • }

  16. 单向多对一! • @Entity • public class Employee { • private Address address; • @ManyToOne • public Address getAddress() { • return address; • } • public void setAddress(Address address) { • this.address = address; • } • ... • } • @ • Entity • public class Address { • ... • }

  17. 双向多对多关系! • @Entity • public class Project { • private Collection<Employee> employees; • @ManyToMany • public Collection<Employee> getEmployees() { • return employees; • } • public void setEmployees(Collection<Employee> employees) { • this.employees = employees; • } • ... • }

  18. @Entity • public class Employee { • private Collection<Project> projects; • @ManyToMany(mappedBy="employees") • public Collection<Project> getProjects() { • return projects; • } • public void setProjects(Collection<Project> projects) { • this.projects = projects; • } • ... • }

  19. 延迟加载 • # FetchType.EAGER:代表立即加载 • # FetchType.LAZY:代表延迟加载

  20. 多级级联 • 级联方式 • ---REFRESH:指定当在你访问期间,如果数据库数据发生变动时,你的数据是否更新 • ---PERSIST:指定在保存1的数据时是否会同时保存级联的n数据。 • ---MERGE:指定当1处于游离状态被修改了,n的数据也有修改,MERGE可以在对1进行更新的同时也对n方进行更新 • ---REMOVE:指定在删除1时是否删除与之级联的n方 • ---ALL:指定包含所有级联的n方

  21. 如何新建实例 • 打开MyEclipse新建立一个WEB项目 • 添加开发JPA依赖的jar包。 • 在类路径的META-INF目录下添加persistence.xml配置文件

  22. @Entity • publicclass User { • private Long id;private String userName; • private Collection<UserRole> userRoles = new HashSet<UserRole>(); • @Id • @GeneratedValue(strategy = GenerationType.IDENTITY) • public Long getId() {return id;} • publicvoid setId(Long id) { • this.id = id; • } • public String getUserName() { • return userName; • } • publicvoid setUserName(String userName) { • this.userName = userName; • } • @OneToMany(mappedBy = "user") • public Collection<UserRole> getUserRoles() { • return userRoles; • } • publicvoid setUserRoles(Collection<UserRole> userRoles) { • this.userRoles = userRoles; • } • }

  23. 角色 • @Entity • public class Role { • private Long id; • private String roleName;// 角色名称 • private Collection<UserRole> userRoles = new HashSet<UserRole>(); • @Id • @GeneratedValue(strategy = GenerationType.IDENTITY) • public Long getId() { • return id; • } • public void setId(Long id) { • this.id = id; • } • public String getRoleName() { • return roleName; • } • public void setRoleName(String roleName) { • this.roleName = roleName; • } • @OneToMany(mappedBy = "role") • public Collection<UserRole> getUserRoles() { • return userRoles; • } • public void setUserRoles(Collection<UserRole> userRoles) { • this.userRoles = userRoles; • } • }

  24. 用户角色 • @Entity • public class UserRole { • private Long id; • private Role role; • private User user; • @Id • @GeneratedValue(strategy = GenerationType.IDENTITY) • public Long getId() { • return id; • } • public void setId(Long id) { • this.id = id; • } • @ManyToOne(cascade = CascadeType.ALL) • public Role getRole() { • return role; • } • public void setRole(Role role) { • this.role = role; • } • /** • * 延迟加载EAGER表示查询的时候已经全部加载lazy表示使用的时候才开始加载 • * • * @return • */ • @ManyToOne(fetch = FetchType.LAZY) • public User getUser() { • return user; • } • public void setUser(User user) { • this.user = user; • } • }

  25. 增加数据测试用例 public class UserTest { • /** • * • */ • EntityManagerFactory factory = Persistence • .createEntityManagerFactory("jpaPU"); • EntityManager em = factory.createEntityManager(); • @Test • public void testSava() { • try { • em.getTransaction().begin(); • User user = new User(); • user.setUserName("xukeping2"); • user.setPasswrod("xukeping2"); • user.setDescription("travelProfile"); • em.persist(user); • em.flush(); • em.getTransaction().commit(); • em.close(); • factory.close(); • } catch (Exception e) { • e.printStackTrace(); • } • } }

  26. 查询单表测试用例 public class UserTest { • /** • * • */ • EntityManagerFactory factory = Persistence • .createEntityManagerFactory("jpaPU"); • EntityManager em = factory.createEntityManager(); • @Test • @SuppressWarnings("unchecked") • public void testQuery() { • try { • em.getTransaction().begin(); • List<User> users = (List<User>) em.createQuery("from User") • .getResultList(); • for (Iterator iterator = users.iterator(); iterator.hasNext();) { • User role = (User) iterator.next(); • System.out.println(role.getId() + " " + role.getUserName()); • } • em.close(); • factory.close(); • } catch (Exception e) { • e.printStackTrace(); • } • }}

  27. 延迟加载测试用例 • @Test • @SuppressWarnings("unchecked") • public void testFetchType() { • try { • em.getTransaction().begin(); • List<UserRole> userRoles = (List<UserRole>) em.createQuery( • "from UserRole").getResultList(); • UserRole userRole = (UserRole) userRoles.get(1); • System.out.println("开始......."); • System.out.println("userRole" + userRole.getUser().getUserName()); • System.out.println("结束......."); • em.close(); • factory.close(); • } catch (Exception e) { • e.printStackTrace(); • } • } • @ManyToOne(fetch = FetchType.LAZY) • 注意:当程序运行到userRole.getUser().getUserName())时,JPA会自动查询JPQLselect user0_.id as id9_0_, user0_.description as descript2_9_0_, user0_.passwrod as passwrod9_0_, user0_.userName as userName9_0_ from User user0_ where user0_.id=?;这就是延迟加载的作用;

  28. 多级级联测试用例 • /** • * 多级级联 • * • * ---REFRESH:指定当在你访问期间,如果数据库数据发生变动时,你的数据是否更新 • * • * ---PERSIST:指定在保存1的数据时是否会同时保存级联的n数据。 • * • * ---MERGE:指定当1处于游离状态被修改了,n的数据也有修改,MERGE可以在对1进行更新的同时也对n方进行更新 • * • * ---REMOVE:指定在删除1时是否删除与之级联的n方 • */ • @Test • @SuppressWarnings("unchecked") • public void testCascade() { • try { • em.getTransaction().begin(); • UserRole userRole = (UserRole) em.find(UserRole.class, 2l); • System.out.println("结束......." + userRole.getId()); • System.out.println("查询开始......."); • Role role = userRole.getRole(); • role.setRoleName("系统管理员2"); • userRole.setRole(role); • userRole = (UserRole) em.find(UserRole.class, 2l); • System.out.println("结束......." + userRole.getRole().getRoleName()); • em.persist(userRole); • em.getTransaction().commit(); • em.close(); • factory.close(); • } catch (Exception e) { • e.printStackTrace(); • } • }

  29. 多表查询测试用例 • /** • * 多表查询 • */ • @Test • @SuppressWarnings("unchecked") • public void testObjectQuery() { • try { • System.out.println("查询开始......."); • List<Object[]> objs = (List<Object[]>) em.createQuery( • "from UserRole,User,Role ").getResultList(); • for (Object[] objects : objs) { • System.out.println(((UserRole) objects[0]).getId()); • } • em.close(); • factory.close(); • } catch (Exception e) { • e.printStackTrace(); • } • }

More Related