JPA概述

1.1 JPA是什么

JPA (Java Persistence API) Java持久化API。是一套Sun公司 Java官方制定的ORM 方案,是规范,是标准 ,sun公司自己并没有实现

 

关注点: ORM  ,标准 概念 (关键字)

 

1.1.1 ORM是什么

ORM(Object Relational Mapping) 对象关系映射。

问:ORM有什么用?

在操作数据库之前,先把数据表与实体类关联起来。 然后通过实体类的对象操作(增删改查)数据库表,这个就是ORM的行为!

所以:ORM是一个实现使用对象操作数据库的设计思想!!!

通过这句话,我们知道JPA的作用就是通过对象操作数据库的,不用编写sql语句。

1.2 JPA的实现者

既然我们说JPA是一套标准,意味着,它只是一套实现ORM理论的接口。没有实现的代码。

那么我们必须要有具体的实现者才可以完成ORM操作功能的实现!

市场上的主流的JPA框架 (实现者)有:

Hibernate (JBoos)、EclipseTop(Eclipse社区)、OpenJPA (Apache基金会)。

其中Hibernate是众多实现者之中,性能最好的。所以,我们本次教学也是选用Hibernate框架作为JPA的主讲框架。

提醒: 学习一个JPA框架,其他的框架都是一样使用

1.3 JPA的作用是什么(问题)

JPA是ORM的一套标准,既然JPA为ORM而生,那么JPA的作用就是实现使用对象操作数据库,不用写SQL!!!.

问题:数据库是用sql操作的,那用对象操作,由谁来产生SQL?

答:JPA实现框架

入门示例

任何框架的学习,都建议从配置流程图开始。所以我们来一起理解JPA的配置流程图。

2.1 配置流程图

1. 我们需要一个总配置文件persistence.xml存储框架需要的信息 (注意,文件名不要写错,而且必须放在classpath/META-INF文件夹里面)

2. 我们需要一个Persistence持久类对象来读取总配置文件,创建实体管理工厂对象

3. 我们需要实体管理工厂获得数据库的操作对象实体管理对象EntityManager。

4. 我们通过EntityManager操作数据库之前,必须要先配置表与实体类的映射关系,从而实现使用对象操作数据库!!!

2.2 配置步骤说明 

第一步:导入包 (不管什么框架,首先要做的事情)

第二步:创建一个总配置文件

第三步:创建一个JPAUtils获得操作对象EntityManager

第四步:创建一个实体类,并且配置好映射注解

第五步:在总配置文件加载实体类

第六步:测试代码(需求:插入数据到用户表)

2.3 配置步骤 

需求:编写一个JPA的项目,插入一条数据到学生信息表。

2.3.1 第一步:创建Maven项目

说明:我们这里是基于hibernate实现的,所以要导入Hibernate的JPA规范包

--使用maven构建的配置--

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>cn.zj</groupId>

<artifactId>jpa-demo01-start</artifactId>

<version>0.0.1-SNAPSHOT</version>

<dependencies>

 <!-- hibernate框架 实现 JPA 依赖 -->

<dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-entitymanager</artifactId>

    <version>4.3.6.Final</version>

</dependency>

    <!--jdbc驱动 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.40</version>

</dependency>

</dependencies>

</project>

2.3.2 第二步创建一个总配置文件

注意:文件必须放在classpath:/META-INF/persistence.xml 

 

说明:Eclipse已经支持了JPA框架,所有不需要配置xsd文件,直接使用

配置信息如下:

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0" 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_2_0.xsd ">

<persistence-unit name="mysql-jpa">

<!-- 四要素 org.hibernate.cfg.Environment-->

<properties>

<!-- 如果使用Hibernate实现的JPA,使用的就是Hibernate的环境参数 -->

<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />

<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa" />

<property name="hibernate.connection.username" value="root" />

<property name="hibernate.connection.password" value="root" />

<!--可选配置-->

<!--控制台打印sql语句-->

<property name="hibernate.show_sql" value="true" />

<!-- 格式化输出SQL -->

<property name="hibernate.format_sql" value="true" />

</properties>

</persistence-unit>

</persistence>

2.3.3 第三步:封装JPAUtils工具类

创建一个工具类JPAUtils,获得操作对象(EntityManager)

package cn.zj.jpa.util;

import javax.persistence.EntityManager;

import javax.persistence.EntityManagerFactory;

import javax.persistence.Persistence;

public class JPAUtils {

//同一个应用中,应该保证只有一个实例工厂。

public static EntityManagerFactory emf = createEntityManagerFactory();

//1.获得实体管理工厂

private static EntityManagerFactory createEntityManagerFactory(){

EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysql-jpa");

return emf;

}

//2.获得实体管理类对象

public static EntityManager getEntityManger(){

EntityManager entityManager = emf.createEntityManager();

return entityManager;

}

}

2.3.4 第四步创建映射实体类

创建一个映射的实体类,将JPA的映射注解写在实体类里面。

package cn.zj.jpa.entity;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;

//1.指定实体类与表名的关系

//@Entity注解,指定该实体类是一个基于JPA规范的实体类

@Entity

//@Table注解,指定当前实体类关联的表

@Table(name="tb_student")

public class Student {

//@Id注解:声明属性为一个OID属性

@Id

//@GeneratedValue注解,指定主键生成策略

@GeneratedValue(strategy=GenerationType.IDENTITY)

//@Column注解,设置属性与数据库字段的关系,如果属性名和表的字段名相同,可以不设置

@Column(name="stu_id")

private Long stuId;//BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '学生编号',

@Column(name="stu_name")

private String stuName;//VARCHAR(50) NULL DEFAULT NULL COMMENT '学生名字',

@Column(name="stu_age")

private Integer stuAge;//INT(11) NULL DEFAULT NULL COMMENT '学生年龄',

@Column(name="stu_password")

private String stuPassword;//VARCHAR(50) NULL DEFAULT NULL COMMENT '登录密码',

public Student() {

super();

}

//补全get、set方法

}

2.3.5 第五步:在总配置文件中加载映射实体类

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0" 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_2_0.xsd ">

<persistence-unit name="mysql-jpa">

  <!-- 加载实体类

   基于hibernate框架的JPA已经实现了自动载入映射实体类 ,所以不配置也是可以的。建议还是加上配置。如果不写容易忽略加载的实体类有哪些

     -->

    <class>cn.zj.jpa.entity.Student</class>

<!-- 四要素 org.hibernate.cfg.Environment-->

<properties>

<!-- 如果使用Hibernate实现的JPA,使用的就是Hibernate的环境参数 -->

<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />

<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa" />

<property name="hibernate.connection.username" value="root" />

<property name="hibernate.connection.password" value="zj" />

<!--可选配置-->

<!--控制台打印sql语句-->

<property name="hibernate.show_sql" value="true" />

<!-- 格式化输出SQL -->

<property name="hibernate.format_sql" value="true" />

</properties>

</persistence-unit>

</persistence>

2.3.6 第六步:操作实体类保存数据

创建一个StudentDAOTest类,测试保存一个学生。

package cn.zj.jpa;

import javax.persistence.EntityManager;

import javax.persistence.EntityTransaction;

import org.junit.Test;

import cn.zj.jpa.entity.Student;

import cn.zj.jpa.util.JPAUtils;

public class StudentDAOTest {

@Test

public void persist(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

//2、获取事物管理器

EntityTransaction transaction = manager.getTransaction();

transaction.begin();

//3、创建实体对象

Student s=new Student();

s.setStuName("张三");

s.setStuAge(18);

s.setStuPassword("zj");

//4、保存到数据库

manager.persist(s);

//5、提交事物

transaction.commit();

//6、关闭资源

manager.close();

}

}

测试结果

通过操作实体对象保存数据成功!!!

2.4 使用JPA的好处

使用JPA,可以直接使用对象操作数据库,由框架根据映射的关系生成SQL。不用开发人员编写。这样做,开发人员就不用编写SQL语句了

问题:这样有什么好处呢?

答:不同的数据库的SQL语法是有差异,如果不需要编写SQL语句。就屏蔽各种数据库SQL的差异。那么,编写的代码就可以一套代码兼容多种数据库!!!!

JPA实现CRUD

修改StudentDAOTest类,测试crud操作

//通过OID删除

@Test

public void remove(){

//1.获得实体管理类对象

EntityManager entityManager = JPAUtils.getEntityManger();

//2.打开事务

EntityTransaction transaction = entityManager.getTransaction();

//3.启动事务

transaction.begin();

//4.创建数据,删除数据必须使用持久化对象

Student s=entityManager.find(Student.class, 2L);

//5.插入

entityManager.remove(s);;

//6。提交

transaction.commit();

//7.关闭

entityManager.close();

}

//更新

@Test

public void merge(){

//1.获得实体管理类对象

EntityManager entityManager = JPAUtils.getEntityManger();

//2.打开事务

EntityTransaction transaction = entityManager.getTransaction();

//3.启动事务

transaction.begin();

//4.创建数据

Student s=new Student();

s.setStuName("李四");

//更新必须要有一个OID

s.setStuId(3L);

//5.更新

entityManager.merge(s);

//6。提交

transaction.commit();

//7.关闭

entityManager.close();

}

//通过OID获得数据

@Test

public void find(){

//1.获得实体管理类对象

EntityManager entityManager = JPAUtils.getEntityManger();

//通过OID查询数据

Student student = entityManager.find(Student.class, 1L);

System.out.println(student.getStuName());

entityManager.close();

}

//通过OID获得数据

@Test

public void getReference(){

//1.获得实体管理类对象

EntityManager entityManager = JPAUtils.getEntityManger();

/**

* getReference()和find()方法的区别:

* getReference基于懒加载机制,即需要使用对象的时候,才执行查询。

*/

Student student = entityManager.getReference(Student.class, 1L);

System.out.println(student.getStuName());

entityManager.close();

}

JPA常用 API说明

4.1 映射注解说明

注解

说明

@Entity

声明该实体类是一个JPA标准的实体类

@Table

指定实体类关联的表,注意如果不写表名,默认使用类名对应表名。

@Column

指定实体类属性对应的表字段,如果属性和字段一致,可以不写

@Id

声明属性是一个OID,对应的一定是数据库的主键字段

@GenerateValue

声明属性(Object ID)的主键生成策略

@SequenceGenerate

使用SEQUENCE策略时,用于设置策略的参数

@TableGenerate

使用TABLE主键策略时,用于设置策略的参数

@JoinTable

关联查询时,表与表是多对多的关系时,指定多对多关联表中间表的参数。

@JoinColumn

关联查询时,表与表是一对一、一对多、多对一以及多对多的关系时,声明表关联的外键字段作为连接表的条件。必须配合关联表的注解一起使用 <key>

@OneToMany

关联表注解,表示对应的实体和本类是一对多的关系

@ManyToOne

关联表注解,表示对应的实体和本类是多对一的关系

@ManyToMany

关联表注解,表示对应的实体和本类是多对多的关系

@OneToOne

关联表注解,表示对应的实体和本类是一对一的关系

4.2 JPA常用API说明

API

说明

Persistence

用于读取配置文件,获得实体管理工厂

EntityManagerFactory

用于管理数据库的连接,获得操作对象实体管理类

EntityManager

实体管理类,用于操作数据库表,操作对象

EntityTransaction

用于管理事务。开始,提交,回滚

TypeQuery

用于操作JPQL的查询的

Query

用于操作JPQL的查询接口,执行没有返回数据的JPQL(增删改)

CriteriaBuilder

用户使用标准查询接口 Criteria查询接口

JPA多表关联查询 

多个关联查询作用(导航查询):就是实现使用一个实体类对象查询多个表的数据。

配置多表联系查询必须有两个步骤;

(1)、在实体类里面建立表与表之间的关系。 

(2)、在实体类配置关联关系,JPA使用注解配置 

 

多表关联的E-R图如下:

根据ER图,创建数据库表!!!

5.1 一对多实现 (单向)

需求:通过ID查询一条学生表的记录,同时查询该学生的对应的成绩的信息!

5.1.1 说明

如图所示:一个学生可以有多条成绩的记录,一条成绩的记录只属于一个学生,所以学生表与成绩表的关系是一对多的关系。

所以,通过JPA配置一对多的关系,可以通过学生表对应的实体类对象同时获得两个表的数据。

5.1.2 配置步骤

5.1.2.1 第一步创建项目

说明:复制入门示例的项目即可。

5.1.2.2 第二步:创建单表实体类

(1)创建Student类

@Entity

@Table(name="tb_student")

public class Student {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

@Column(name="stu_id")

private Long stuId;

@Column(name="stu_name")

private String stuName;

@Column(name="stu_age")

private Integer stuAge;

@Column(name="stu_password")

private String stuPassword;

public Student() {

super();

}

//补全get、set方法

}

(2)创建Score类

@Entity

@Table(name="tb_score")

public class Score{

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

@Column(name="sco_id")

private Long scoId;

@Column(name="sco_subject")

private String scoSubject;

@Column(name="sco_score")

private Float scoScore;

@Column(name="stu_id")

private Long stuId;

public Score() {

super();

}

// 补全getset方法

}

5.1.2.3 第三步:配置一对多关联关系

说明:通过@OneToMany注解配置。

修改Student类,配置一对多关系。

/**

* 单向一对对,应该有学生来维护关系

*

* 一个学生对应多个成绩,一对多关系

* 多个成绩我们使用list封装起来

*

* JPA 使用 @OneToMany 映射一对多

* fetch : 抓取策略

* FetchType.LAZY 懒加载,默认 (只有关联对象在用到的时候才会去发送新的sql,默认关联对象不会查询)

* 会多生成sql语句 :N+1

* FetchType.EAGER 迫切查询 (多表连接查询,只会发送一条sql语句)

* @JoinColumn 设置两张表之间外键列

*/

@OneToMany(fetch=FetchType.EAGER)

@JoinColumn(name="stu_id")

private List<Score> scores;

public void setScores(List<Score> scores) {

this.scores = scores;

}

5.1.2.4 第四步:测试一对多查询

@Test

public void testOne2Many(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

Student student = manager.find(Student.class, 1L);

System.out.println("学生id:"+student.getStuId()+",学生姓名:"+student.getStuName());

List<Score> scores = student.getScores();

for (Score score : scores) {

System.out.println("科目:"+score.getScoSubject()+",分数:"+score.getScoScore());

}

//6、关闭资源

manager.close();

}

查询结果:

一对多关联查询成功!!!

5.2 多对一实现 (单向)

5.2.1 说明

需求:通过ID查询一条成绩表的记录,同时查询该成绩的对应的学生的信息!

如图所示:成绩表里面,每一条记录只能对应一个学生,但是学生编号不是唯一的。所以成绩表里面的多条数据可以对应一个学生,所以我们称多对一的关系。

5.2.2 配置步骤

5.2.2.1 第一步创建项目

复制一对多示例项目即可。

5.2.2.2 第二步:创建单表实体类

修改Student类,去掉一对多配置即可。

5.2.2.3 第三步:配置多对一关联关系

修改Score类,配置多对一关系

@Entity

@Table(name="tb_score")

public class Score{

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

@Column(name="sco_id")

private Long scoId;

@Column(name="sco_subject")

private String scoSubject;

@Column(name="sco_score")

private Float scoScore;

/**

* jpa的多对一,关联关系中指定的外键  和 关联表的属性有冲突

*    解决的方案:去掉关联表中外键对应的属性

/*@Column(name="stu_id")

private Long stuId;

public Long getStuId() {

return stuId;

}

public void setStuId(Long stuId) {

this.stuId = stuId;

}

*/

/**

* 1、分数和学生信息是多对一的关系

* 2、只需要一个学生的实体来引用学生的信息

*/

@ManyToOne

@JoinColumn(name="stu_id")

private Student student;

public Student getStudent() {

return student;

}

public void setStudent(Student student) {

this.student = student;

}

//补全get、set方法

}

5.2.2.4 第四步:测试

@Test

public void testMany2One(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

Score score = manager.find(Score.class, 1L);

System.out.println("科目:"+score.getScoSubject()+",分数:"+score.getScoScore());

Student student = score.getStudent();

System.out.println("学生id:"+student.getStuId()+",学生姓名:"+student.getStuName());

//6、关闭资源

manager.close();

}

查询结果:

多对一配置成功!!!

5.3 双向一对多|多对一(了解)

5.3.1 说明

(1)查询学生信息,同时查询成绩信息。

(2)查询成绩信息,同时也可以查询学生信息。

5.3.2 配置步骤

在同一个项目中,在Student类和Score类中,同时配置关联关系。

(1)在Student类中配置一对多

@OneToMany   //声明是一对多的关系

@JoinColumn(name="stu_id")   //指定关联表中  外键的字段

private List<Score> scores;

public List<Score> getScores() {

return scores;

}

public void setScores(List<Score> scores) {

this.scores = scores;

}

(2)在Score类中配置多对一

/**

* jpa的多对一,关联关系中指定的外键  和 关联表的属性有冲突

*    解决的方案:去掉关联表中外键对应的属性

@Column(name="stu_id")

private Long stuId;

public Long getStuId() {

return stuId;

}

public void setStuId(Long stuId) {

this.stuId = stuId;

}

*/

/**

* 1、分数和学生信息是多对一的关系

* 2、只需要一个学生的实体来引用学生的信息

*/

@ManyToOne

@JoinColumn(name="stu_id")

private Student student;

public Student getStudent() {

return student;

}

public void setStudent(Student student) {

this.student = student;

}

5.4 一对一实现

5.4.1 说明

需求:通过ID查询学生的信息,通过也获得学生对应的学生身份信息。

5.4.2 配置步骤

5.4.2.1 第一步:创建项目

复制一对多的示例项目即可。

5.4.2.2 第二步:创建单表实体类

(1)创建Student类

(2)创建Identity类

package cn.zj.jpa.entity;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.Table;

@Entity

@Table(name="tb_identity")

public class Identity {

@Id

/*由于一对一,外键表的主键字段值来自于主键表,所以只能手工输入

手工输入ID值,可以不指定主键生成策略 */

// @GeneratedValue

@Column(name="stu_id")

private Long stuId;

@Column(name="stu_identity")

private String stuIdentity;

@Column(name="stu_no")

private String stuNo;

@OneToOne

//2.必须要指定关联的外键

@JoinColumn(name="stu_id")

private Student student;

public Identity() {

super();

}

// 补全get、set方法

}

5.4.2.3 第三步配置一对一关联关系

说明:一对一关联关系,也是支持双向配置的。

可以在Student类、Identity类中同时配置关联关系。

(1)修改Student类,配置一对一关系。

//学生表与学生身份表是一对一的关系,意味着,一个学生只能对应一条学生身份信息

//所以使用引用

//1.声明关系,一对一

@OneToOne

//2.必须要指定关联的外键

@JoinColumn(name="stu_id")

private Identity identity;

public Identity getIdentity() {

return identity;

}

public void setiIdentity(Identity identity) {

this.identity = identity;

}

(2)修改Score类

//1.声明关系,一对一

@OneToOne

//2.指定关联的外键

@JoinColumn(name="stu_id")

private Student student;

public Student getStudent() {

return student;

}

public void setStudent(Student student) {

this.student = student;

}

5.4.2.4 第四步:测试

说明:可以分别测试方向一对一关系。

@Test

public void testOne2One1(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

Student student = manager.find(Student.class, 1L);

System.out.println("学生id:"+student.getStuId()+",学生姓名:"+student.getStuName());

Identity identity = student.getIdentity();

System.out.println("学生学号:"+identity.getStuNo()+",身份证号:"+identity.getStuIdentity());

//6、关闭资源

manager.close();

}

@Test

public void testOne2One2(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

Identity identity = manager.find(Identity.class, 1L);

System.out.println("学生学号:"+identity.getStuNo()+",身份证号:"+identity.getStuIdentity());

Student student = identity.getStudent();

System.out.println("学生id:"+student.getStuId()+",学生姓名:"+student.getStuName());

//6、关闭资源

manager.close();

}

(1)测试学生关联身份信息

测试结果:

(2)测试身份信息关联学生。

一对一配置成功!!!

5.5 配置多对多

5.5.1 说明

需求:

(1)通过ID查询学生的信息,通过该学生信息也获得对应的教师信息。

(2)通过ID查询教师的信息,通过教师信息也获得该对应的学生信息。

如图所示:一个学生可以有多个教师,一个教师也可以有多个学生,所以学生和教师的关系是多对多的关系。

如上图所示:

如果要从学生表的信息获得教师表的信息。必须需要三个条件

1. 必须需要有一个中间表

2. 必须需要中间表对应本表的外键

3. 必须需要中间表对应关联表的外键

5.5.2 配置步骤

5.5.2.1 第一步:创建项目

复制一个示例项目即可。

5.5.2.2 第二步:创建单表实体类

学生实体类Student

//1.指定实体类与表名的关系

//@Entity注解,指定该实体类是一个基于JPA规范的实体类

@Entity

//@Table注解,指定当前实体类关联的表

@Table(name="tb_student")

public class Student {

//@Id注解:声明属性为一个OID属性

@Id

//@GeneratedValue注解,指定主键生成策略

@GeneratedValue(strategy=GenerationType.IDENTITY)

//@Column注解,设置属性与数据库字段的关系,如果属性名和表的字段名相同,可以不设置

@Column(name="stu_id")

private Long stuId;//BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '学生编号',

@Column(name="stu_name")

private String stuName;//VARCHAR(50) NULL DEFAULT NULL COMMENT '学生名字',

@Column(name="stu_age")

private Integer stuAge;//INT(11) NULL DEFAULT NULL COMMENT '学生年龄',

@Column(name="stu_password")

private String stuPassword;//VARCHAR(50) NULL DEFAULT NULL COMMENT '登录密码',

public Student() {

super();

}

//补全get、set方法

}

教师实体类Teacher

@Entity

@Table(name="tb_teacher")

public class Teacher {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

@Column(name="tea_id")

private Long teaId;

@Column(name="tea_name")

private String teaName;

@Column(name="tea_password")

private String teaPassword;

public Teacher() {

super();

}

//补全get、set方法

}

5.5.2.3 第三步:配置多对多关系

(1)学生关联教师,修改Student类

// 学生表和教师表是多对多的关系

// 所以,一个学生可以有多个教师,所以需要使用集合来存储教师信息

//1.声明关系,多对多

@ManyToMany

//2.设置关联的条件

//JoinTable用于对应中间表的设置     joinColumns设置中间表与本表关联的外键    inverseJoinColumns设置中间表与关联表对应的外键

@JoinTable(name="tb_stu_tea" ,joinColumns=@JoinColumn(name="stu_id"),inverseJoinColumns=@JoinColumn(name="tea_id"))

private List<Teacher> teachers;

public List<Teacher> getTeachers() {

return teachers;

}

public void setTeachers(List<Teacher> teachers) {

this.teachers = teachers;

}

(2)教师关联学生,修改Teacher类

//因为教师与学生是多对多的关系,所以一个教师也可以有多个学生,需要使用集合来存储学生的数据

//1.声明教师和学生的关系,多对多

@ManyToMany

//2.设置关联的条件

@JoinTable(name="tb_stu_tea" ,joinColumns=@JoinColumn(name="tea_id"),inverseJoinColumns=@JoinColumn(name="stu_id"))

private List<Student> students;

public List<Student> getStudents() {

return students;

}

public void setStudents(List<Student> students) {

this.students = students;

}

5.5.2.4 测试

5.5.2.4.1 Step1:测试学生关联教师

测试代码

@Test

public void testMany2Many1(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

Student student = manager.find(Student.class, 1L);

System.out.println("学生id:"+student.getStuId()+",学生姓名:"+student.getStuName());

List<Teacher> teachers = student.getTeachers();

for (Teacher teacher : teachers) {

System.out.println("教师id:"+teacher.getTeaId()+",教师姓名:"+teacher.getTeaName());

}

//2、关闭资源

manager.close();

}

测试结果:

5.5.2.4.2 Step2:测试教师关联学生

测试代码

@Test

public void testMany2Many2(){

//1.获得实体管理类

EntityManager manager = JPAUtils.getEntityManger();

Teacher teacher = manager.find(Teacher.class, 1L);

System.out.println("教师id:"+teacher.getTeaId()+",教师姓名:"+teacher.getTeaName());

List<Student> students = teacher.getStudents();

for (Student student : students) {

System.out.println("学生id:"+student.getStuId()+",学生姓名:"+student.getStuName());

}

//2、关闭资源

manager.close();

}

测试结果:

多对多配置成功!!!

转载于:https://www.cnblogs.com/aknife/p/11304973.html

JPA 一对一 一对多 多对一 多对多配置相关推荐

  1. 初学者易上手的SSH-hibernate04 一对一 一对多 多对多

    这章我们就来学习下hibernate的关系关联,即一对一(one-to-one),一对多(one-to-many),多对多(many-to-many).这章也将是hibernate的最后一章了,用于初 ...

  2. mybatis的一对一 一对多 多对多

    mybatis的一对一 一对多 多对多 1.表 2.建表语句 order_t表 CREATE TABLE `order_t` ( `id` int(11) NOT NULL, `user_id` in ...

  3. SQLAlchemy_定义(一对一/一对多/多对多)关系

    SQLAlchemy_定义(一对一/一对多/多对多)关系 目录 Basic Relationship Patterns One To Many One To One Many To Many Basi ...

  4. 一对一 一对多 多对多

    一对一 例如,学校里一个班级只有一个正班长,而一个班长只在一个班中任职,则班级与班长之间具有一对一联系. 一对多 例如,一个班级中有若干名学生,而每个学生只在一个班级中学习,则班级与学生之间具有一对多 ...

  5. EF里一对一、一对多、多对多关系的配置和级联删除

    EF里一对一.一对多.多对多关系的配置和级联删除 本章节开始了解EF的各种关系.如果你对EF里实体间的各种关系还不是很熟悉,可以看看我的思路,能帮你更快的理解. I.实体间一对一的关系 添加一个Per ...

  6. day 69-70 一对一 一对多 多对一联表查询

    day 69 orm操作之表关系,多对多,多对一多对一/一对多,多对多{类中的定义方法}day691. 昨日内容回顾1. 单表增删改查2. 单表查询API返回QuerySet对象的:1. .all() ...

  7. 7. MyBatis多表查询 - 一对一 - 一对多 - 多对多

    7. MyBatis多表查询 - 一对一 - 一对多 - 多对多 前言 在前面的篇章,我们已经熟悉了单表查询,下面我们来看看如何进行 多表查询. 数据准备 create database if not ...

  8. Mybatis中的关系映射(一对一,一对多,多对多)

    在网上寻了很久,大多数讲关系性的文章都是大篇幅的去将表照搬上来,本来就很生硬,此文就不在讲述关系性映射的具体实现,转而从浅层来讲讲其概念性. 1.1 关联关系概述 在关系型数据库中,多表之间存在着三种 ...

  9. Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作

    Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作,单表查询,多表查询 一丶表与表之间的关系 背景: ​ ​ ​  ​ ​ 由于如果只使用一张表存储所有的数据,就会操作数 ...

最新文章

  1. idea代码回滚_IDEA远程仓库版本回滚
  2. Madagascar的宏定义函数--判断整数的奇偶性函数
  3. springboot 启动加载数据库数据到redis缓存
  4. VirtuoZo数字摄影测量(一)——单模型的建立
  5. /usr/bin/sed: No such file or directory
  6. linux scp 非22端口,[ssh scp sftp] 连接远程ssh非22端口的服务器方法
  7. java框架有哪几种,java权限框架有几种?常见的权限框架分享
  8. 又一个PS2汉化入门
  9. MFC API 设置Excel单元格格式
  10. Android P Asan使用总结
  11. 微信大数据:中国人怎么过国庆长假?
  12. 看不见的竞争 之 把握意见领袖
  13. GPT:Improving Language Understanding by Generative Pre-Training(2018-6-12)
  14. 北大计算机所孙俊教授,教育部人工智能咨询专家孙俊:科技怎样赋能智慧教育?...
  15. fan类java_(Fan类)(Fan class)
  16. 用html和js编写黑洞数,黑洞数及其简单理论
  17. 基于激光雷达slam的无人车室内导航比较分析
  18. 偏微分方程简明教程第三章部分答案
  19. VSCode设置Tab缩进两个空格
  20. 奥巴马胜选演说•文言版

热门文章

  1. 据说黑白红客大多是出身测试行业,那么前戏如何做好呢?戳下
  2. 产品经理必备技能:业务流程图
  3. RGH reset glitch hack
  4. nginx跨域访问设置
  5. # HTML5期末大作业:海贼王影视网站设计——仿京东-海贼王(1页) HTML+CSS+JavaScript 学生DW网页设计作业成品 wweb前端期末大作业 网页设计实例 企业网站制作
  6. 【模型推理加速系列】06: 基于resnet18加速方案评测
  7. windows安装使用MyBatis Migrations
  8. FairFuzz: A Targeted Mutation Strategy for Increasing Greybox Fuzz Testing Coverage
  9. 笔记-qemu sriov环境配置
  10. ​gdal_retile.py 重切片工具官方文档