`
aaagu1234
  • 浏览: 144826 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JPA一对多,多对多映射

阅读更多
JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术
总的来说,JPA包括以下3方面的技术:
ORM映射元数据
Java持久化API
查询语言

采用JPA的实现hibernate开发必须的包
hibernate核心包hibernate-distribution-3.3.1.GA
hibernate3.jar
lib\bytecode\cglib\hibernate-cglib-repack-2.1_3.jar
lib\required\*.jar
Hiberante注解包hibernate-annotations-3.4.0.GA
hibernate-annotations.jar
lib\ejb3-persistence.jar、hibernate-commons-annotations.jar
Hibernate针对JPA的实现包hibernate-entitymanager-3.4.0.GA
hibernate-entitymanager.jar
lib\test\log4j.jar、slf4j-log4j12.jar

JPA的配置文件
JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的,配置模版如下:
<?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="itcast" transaction-type="RESOURCE_LOCAL">
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
         <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver"/>
         <property name="hibernate.connection.username" value="root"/>
         <property name="hibernate.connection.password" value="123456"/>
         <property name="hibernate.connection.url"        value="jdbc:mysql://localhost:3306/itcast?useUnicode=true&amp;characterEncoding=UTF-8"/>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
      </properties>
  </persistence-unit>
</persistence>

JPA事务
RESOURCE_LOCAL本地事务、JTA(全局事务)

持久化API
EntityManager
persist(Object)     持久化
remove(Object)     删除对象
find(Class entityClass,Object key) 根据主键查询
getReference(Class entityClass,Object key)根据主键查询
flush()     实体与底层同步,执行sql
createQuery() 创建JPQL查询对象
createNativeQuery() 根据普通SQL查询
createNamedQuery() 命名查询@NamedQuerie标注   
merge(Object) 将一个detached的实体持久化到EntityManager中
close()    关闭管理器
find()与getReference()区别
find()不支持延迟加载,无记录返回NULL
getReference()支持延迟加载,getReference()不会返回null值,而是抛出EntityNotFoundException

javax.persistence.Query           
int executeUpdate() 执行更新、删除、添加
Object getSingleResult() 执行查询(返回一条记录)   
List getResultList() 执行查询(返回结果链表)
Query setParameter(int position,object value) 给Query对象设置参数
Query setMaxResults(int maxResult) 给Query对象设置返回数 分页查询
Query setFirstResult(int firstResult) 给Query对象设置返回偏移

JPA一对多双向
1-m:多的一方为关系维护端,关系维护端负责外键纪录的更新,关系被维护端没有权力更新外键纪录.
维护端注解
拥有mappedBy注解的实体类为关系被维护端,另外的实体类为关系维护端的。顾名思意,关系的维护端对关系(在多对多为中间关联表)的CRUD做操作。关系的被维护端没有该操作,不能维护关系。

@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
@JoinColumn(name = "order_id")
被维护端注解
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
            CascadeType.MERGE, CascadeType.REMOVE },
                      &nbsp;fetch = FetchType.EAGER,
                      &nbsp;mappedBy = "order")

@Entity
@Table(name = "order_info")
public class OrderInfo {
    private Integer id;
    private String name;
    private Set<OrderItem> items = new HashSet<OrderItem>();
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
            CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER,
                       mappedBy = "order")
    public Set<OrderItem> getItems() {
        return items;
    }
    public void setItems(Set<OrderItem> items) {
        this.items = items;
    }
    public void addOrderItem(OrderItem orderItem) {
        orderItem.setOrder(this);
        this.items.add(orderItem);
    }
}

@Entity
@Table(name = "order_item")
public class OrderItem {
    private Integer Id;
    private String name;
    private OrderInfo order;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return Id;
    }
    public void setId(Integer id) {
        Id = id;
    }
    @Column(length = 20, nullable = true)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH }, optional = false)
    @JoinColumn(name = "order_id")
    public OrderInfo getOrder() {
        return order;
    }
    public void setOrder(OrderInfo order) {
        this.order = order;
    }
}

测试
public class OneToMany {
    @Test
    public void save() {
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("JPAPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        OrderInfo o = new OrderInfo();
        o.setName("订单一");
        OrderItem oi1 = new OrderItem();
        oi1.setName("产品一");
        o.addOrderItem(oi1);
        OrderItem oi2 = new OrderItem();
        oi2.setName("产品一");
        o.addOrderItem(oi2);
        OrderItem oi3 = new OrderItem();
        oi3.setName("产品一");
        o.addOrderItem(oi3);
        OrderItem oi4 = new OrderItem();
        oi4.setName("产品一");
        o.addOrderItem(oi4);
        em.persist(o);
        // UUID.randomUUID().toString();
        em.getTransaction().commit();
        emf.close();
    }
}

JPA多对多双向
维护端注解
@ManyToMany (cascade = CascadeType.REFRESH)
@JoinTable (//关联表
                   name =  "student_teacher" , //关联表名
                   inverseJoinColumns =  @JoinColumn (name =  "teacher_id" ),//被维护端外键
                   joinColumns =  @JoinColumn (name =  "student_id" ))//维护端外键
被维护端注解
@ManyToMany(
                   cascade = CascadeType.REFRESH,
                   mappedBy = "teachers",//通过维护端的属性关联
                   fetch = FetchType.LAZY)
@Entity
public class Student {
    private Integer id;
    private String name;
    private Set<Teacher> teachers = new HashSet<Teacher>();
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    @Column(nullable = false, length = 16)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @ManyToMany(cascade = CascadeType.REFRESH)
    @JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name = "student_id"))
    public Set<Teacher> getTeachers() {
        return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }
    public void addTeacher(Teacher teacher) {
        this.teachers.add(teacher);
    }
    public void removeTeachers(Teacher teacher) {
        this.teachers.remove(teacher);
    }
}
@Entity
public class Teacher {
    private Integer id;
    private String name;
    private Set<Student> students = new HashSet<Student>();
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    @Column(nullable = false, length = 16)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

测试
public class ManyToMany {
    @Test
    public void save() {
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("JPAPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Student student = new Student();
        student.setName("小李");
        Teacher teacher = new Teacher();
        teacher.setName("大李");
        em.persist(student);
        em.persist(teacher);
        em.getTransaction().commit();
        emf.close();
    }
   
    @Test
    public void bind() {
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("JPAPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Student student = em.find(Student.class, 1);
        Teacher teacher = em.find(Teacher.class, 1);
        student.addTeacher(teacher);
        em.persist(student);
        em.getTransaction().commit();
        emf.close();
    }
   
    @Test
    public void unbind() {
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("JPAPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Student student = em.find(Student.class, 1);
        Teacher teacher = em.find(Teacher.class, 1);
        student.removeTeachers(teacher);
        em.persist(student);
        em.getTransaction().commit();
        emf.close();
    }
   
    @Test
    public void removeTeacher() {
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("JPAPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        // 关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败
        em.remove(em.getReference(Teacher.class, 1));
        em.getTransaction().commit();
        emf.close();
    }
   
    @Test
    public void removeStudent() {
        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("JPAPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        // 关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息
        em.remove(em.getReference(Student.class, 1));
        em.getTransaction().commit();
        emf.close();
    }
   
}


常见异常
1、异常信息:org.hibernate.hql.ast.QuerySyntaxException: person is not mapped
异常环境:查询
异常原因:查询语句中Person类没有大写

2、java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.lang.String
异常环境:查询、遍历显示
异常原因:转型出错

3、javax.persistence.NonUniqueResultException: result returns more than one elements
异常环境:查询、getSingleResult
异常原因:getSingleResult只能获取一条数据,而查询语句返回的是多条数据

4、 org.hibernate.PropertyValueException: not-null property references a null or transient value: com.sunyard.entities.Person.name
异常环境:数据插入
异常原因:JPA的Entity中一个属性定义为nullable=false,插入数据该字段为null

5、 执行添加没反应、没异常
异常原因:没有开启事务、没有提交事务

6、javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.sunyard.entities.Person
异常环境:OneToOne 共享主键关联
异常原因:一对一中,一个提供主键、另一个共享其主键,共享主键的对象可以set 提供主键的对象 然后添加到数据库中
方向弄反了 后果就是没人提供主键

7、org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:            
异常环境:多对一添加
异常原因:在多的一端维护 ,没有添加级联

8、javax.persistence.PersistenceException: [PersistenceUnit: JPA] Unable to configure EntityManagerFactory
异常原因:很多、实体管理器Factory没有成功创建,是注解的问题
9、org.hibernate.MappingException: Unable to find column with logical name: sid in org.hibernate.mapping.
异常环境:添加表做多对一关联映射
异常原因:表字段写反了,name添加表字段名referencedColumnName指向本表字段名


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/LJHABC1982/archive/2011/06/20/6556580.aspx
分享到:
评论
1 楼 hekuilove 2015-06-07  
楼主 介意把你的代码放到
//代码 
里么

相关推荐

    JPA一对一,一对多,多对多关系映射

    JPA一对一,一对多,多对多关系映射,面向对象领域

    JPA一对多映射关系解析

    为了方便广大开发朋友的需要特整理一下有关jpa映射关系,希望可以帮助到一些朋友。

    自己做的一个jpa多对多映射的一个例子

    刚学完了hibernate和ejb,自己又自学了下jpa,看了黎活明老师的视频,自己做了个多对多的例子,希望可以对你学习有所帮助,有心人可以联系我QQ770256061!

    hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了

    hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了

    jpa的实体映射关系7种

    单向一对一 双向一对一 单向一对多 双向一对多 双向多对一 单向多对多 双向多对多

    尚硅谷JPA视频教程

    JPA视频_映射单向一对多的关联关系 · 14. JPA视频_映射双向一对多的关联关系 · 15. JPA视频_映射双向一对一的关联关系 · 16. JPA视频_映射双向多对多的关联关系 · 17. JPA视频_二级缓存 · 18. JPA视频_...

    JPA-4 映射关联关系

    映射单向多对一、单向一对多、双向一对一、双向多对一和双向多对多关联关系的具体实现

    hibernate的中所有关系映射(分别用xml和jpa实现)

    hibernate的中关系映射分为一对一、一对多、多对一、多对多,其中有单双向之分。而一对一还有主键和外键区分。一共是九种。分别用xml配置文件和annotation实现。annotation的版本没有写测试程序,见谅。

    JPA2映射的神秘之旅

    JPA2映射的神秘之旅,介绍JPA的标准规范以及注解声明的使用,对已如何做一对多,多对一有详细的说明!

    OpenJPA 2.2.1 API (CHM格式)

     除了对 JPA 标准的支持之外,OpenJPA 还提供了非常多的特性和工具支持让企业应用开发变得更加简单,减少开发者的工作量,包括允许数据远程传输/离线处理、数据库/对象视图统一工具、使用缓存(Cache)提升企业应用...

    jpa-onetomany-springboot-maven-mysql:使用Spring Boot,Maven和MySQL的JPA一对多关系映射示例

    Spring Boot,Maven和MySQL的JPA一对多关系示例 指南 先决条件 JDK 1.8或更高版本 Maven 3或更高版本 MySQL 5.6或更高版本 叠放 Spring Data JPA Sprint Boot MySQL 跑 mvn spring-boot:run

    MyEclipse JPA 教程

     JPA是一个新的类似Hibernate的持久化规范,它已经成为Java EE5规范的一部分。JPA使用Java 5的注解(annotation)来控制将单纯Java类(POJO对象)映射到数据库中的表。MyEclipse的JPA工具提供了功能强大的生成和...

    CH02-关联映射、缓存.pptx

    熟练使用JPA的关联映射 多对一,一对多单向 双向多对一关联 双向一对一关联 双向多对多关联 会使用JPA的二级缓存

    SpringBoot使用Spring-data-jpa简化数据访问层

    对数据库的操作无非就“增删改查”。就最为普遍的单表操作而言,除了表和字段不同外,语句都是类似的,开发人员需要写...Spring-data-jpa的出现正可以让这样一个已经很“薄”的数据访问层变成只是一层接口的编写方式。

    bookManager:用于Spring Boot的Book Manager一对多关系项目

    一对多双向关系映射带有Spring Boot的Java Web Services和RESTful API 本教程将引导您完成使用Spring Boot,Spring Data JPA,Lombok,H2和Swagger映射JPA / Hibernate一对多双向关系的步骤。 下表关系图说明了此...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    第三部分提供了一个jsf+ejb 3+ jpa整合开发的项目:电子拍卖系统。这个项目包括5个实体,这5个实体之间具有复杂的关联关系,而且业务逻辑也相对复杂,希望让读者理论联系实际,真正将jsf+ejb 3+jpa整合真正运用到...

    jpa-workshop:在我的 JPAHibernate 研讨会中使用的一系列示例

    一对多/多对一 多对多 嵌入式 辅助表 遗产 懒惰抓取 查询 JPQL 命名查询 Spring数据 本机 SQL 乐观锁 复合键(进行中) 去做 添加复合键的更多示例 添加三元键的例子 以上两者混合关联 用户类型(包括 ID 字段的...

    开发JPA应用

    13.4.4 生成一对多等复杂映射代码.......................... 49 13.5 Spring整合JPA开发................................... 58 13.5.1 添加Spring开发功能................................ 59 13.5.2 从...

    JAVA基础知识点HTML格式教程编程实例20000源代码

    非常适合初学者 ... ---------------------------------------------- ...命名查询、本地查询、一对多映射、一对一映射、开放JPA、分页结果集合 主关键词、查询参数、结果映射、保存、二级表、自联接 ... ... 太多知识点了

    Hibernate_JPA

    关于Hibernate的基本知识,有关关联映射,二级缓存,一对多,多对一,HQL查询等等.

Global site tag (gtag.js) - Google Analytics