JPA一对多,多对多映射[转]

JPA(Java PersistenceAPI)是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"?>
<persistencexmlns="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="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"/>
        <propertyname="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 {
    privateInteger id;
    privateString name;
    privateSet<OrderItem> items = newHashSet<OrderItem>();
    @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
    publicInteger getId() {
       return id;
    }
    public voidsetId(Integer id) {
       this.id = id;
    }
    publicString getName() {
       return name;
    }
    public voidsetName(String name) {
       this.name = name;
    }
   @OneToMany(cascade = { CascadeType.PERSIST,CascadeType.REFRESH,
           CascadeType.MERGE, CascadeType.REMOVE }, fetch =FetchType.EAGER,
                      mappedBy = "order")
    publicSet<OrderItem> getItems() {
       return items;
    }
    public voidsetItems(Set<OrderItem> items){
       this.items = items;
    }
    public voidaddOrderItem(OrderItem orderItem) {
       orderItem.setOrder(this);
       this.items.add(orderItem);
    }
}

@Entity
@Table(name = "order_item")
public class OrderItem {
    privateInteger Id;
    privateString name;
    privateOrderInfo order;
    @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
    publicInteger getId() {
       return Id;
    }
    public voidsetId(Integer id) {
       Id = id;
    }
   @Column(length = 20, nullable = true)
    publicString getName() {
       return name;
    }
    public voidsetName(String name) {
       this.name = name;
    }
   @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH },optional = false)
   @JoinColumn(name = "order_id")
    publicOrderInfo getOrder() {
       return order;
    }
    public voidsetOrder(OrderInfo order) {
       this.order = order;
    }
}

测试
public class OneToMany {
    @Test
    public voidsave() {
       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 {
    privateInteger id;
    privateString name;
    privateSet<Teacher> teachers = newHashSet<Teacher>();
    @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
    publicInteger getId() {
       return id;
    }
    public voidsetId(Integer id) {
       this.id = id;
    }
   @Column(nullable = false, length = 16)
    publicString getName() {
       return name;
    }
    public voidsetName(String name) {
       this.name = name;
    }
   @ManyToMany(cascade = CascadeType.REFRESH)
   @JoinTable(name = "student_teacher", inverseJoinColumns =@JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name ="student_id"))
    publicSet<Teacher> getTeachers() {
       return teachers;
    }
    public voidsetTeachers(Set<Teacher> teachers){
       this.teachers = teachers;
    }
    public voidaddTeacher(Teacher teacher) {
       this.teachers.add(teacher);
    }
    public voidremoveTeachers(Teacher teacher) {
       this.teachers.remove(teacher);
    }
}
@Entity
public class Teacher {
    privateInteger id;
    privateString name;
    privateSet<Student> students = newHashSet<Student>();
    @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
    publicInteger getId() {
       return id;
    }
    public voidsetId(Integer id) {
       this.id = id;
    }
   @Column(nullable = false, length = 16)
    publicString getName() {
       return name;
    }
    public voidsetName(String name) {
       this.name = name;
    }
   @ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers",fetch = FetchType.LAZY)
    publicSet<Student> getStudents() {
       return students;
    }
    public voidsetStudents(Set<Student> students){
       this.students = students;
    }
}

测试
public class ManyToMany {
    @Test
    public voidsave() {
       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 voidbind() {
       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 voidunbind() {
       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 voidremoveTeacher() {
       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 voidremoveStudent() {
       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 notmapped
异常环境:查询
异常原因:查询语句中Person类没有大写

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

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

4、 org.hibernate.PropertyValueException: not-null propertyreferences 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 topersist: com.sunyard.entities.Person
异常环境:OneToOne 共享主键关联
异常原因:一对一中,一个提供主键、另一个共享其主键,共享主键的对象可以set 提供主键的对象 然后添加到数据库中
方向弄反了 后果就是没人提供主键

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值