参考博客:https://blog.csdn.net/baidu_37107022/article/details/76572195

常用注解:

https://blog.csdn.net/eastlift/article/details/2463243

https://www.cnblogs.com/a8457013/p/7753575.html

https://blog.csdn.net/u014421556/article/details/52040263

----------------------

所需jar

persistence.xml(注意文件的位置一定要在类路径下META-INF文件夹下)

<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<!-- 事务类型使用本地事务 -->
<persistence-unit name="simple" transaction-type="RESOURCE_LOCAL"> <properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="jay571018"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3308/jpatest?useUnicode=true&amp;characterEncoding=UTF-8" />
<!--
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3308/jpatest?useUnicode=true&amp;characterEncoding=UTF-8" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="jay571018"></property>
-->
</properties>
</persistence-unit>
</persistence>

---------------------------------------

实体类:Person

package org.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType; @Entity
//@Table(name="xxx") 创建的表名称为xxx 如果不写 默认为类名称首字母小写
public class Person {
private Integer id;
private String name;
private Date birthday;
//性别
private Gender gender=Gender.Man;//默认值为Man public Person() {} public Person(String name) {
super();
this.id = id;
this.name = name;
} public Person(String name, Date birthday) {
super(); this.name = name;
this.birthday = birthday;
} //可省略 默认为自动生成策略
//数据库中的主键字段名称为id 主键增长类型为自动选择
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
//数据库中的字段personame和该实体类中的name属性进行映射 不为空 长度为10
@Column(length=10,name="personname",nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//TemporalType.DATE:数据格式为2018-04-04 数据库字段类型为date
//TemporalType.TIMESTAMP:数据格式为2018-04-03 20:56:53 数据库字段类型为datetime
@Temporal(TemporalType.TIMESTAMP)
public Date getBirthday() {
return birthday;
} public void setBirthday(Date birthday) {
this.birthday = birthday;
} //EnumType.STRING保存进数据库时 是字符串的形式 Man或者Momen
//EnumType.ORDINAL保存进数据库时 是以索引值的形式 0或者1
@Enumerated(EnumType.STRING) @Column(nullable=false,length=5)
public Gender getGender() {
return gender;
} public void setGender(Gender gender) {
this.gender = gender;
} }

实体类:Gender

package org.model;
//创建枚举 性别
public enum Gender {
Man,Women
}

建表和插入测试:

    //建表测试
@Test
public void createtable() {
//该方法中的参数就是配置文件中 持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
factory.close();
} //插入测试
@Test
public void save() {
//该方法中的参数就是配置文件中 持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();//开启事务
em.persist(new Person("张三",new Date()));//持久化 即保存一个对象到数据库中
em.getTransaction().commit();//提交事务
em.close();
factory.close();
}

数据库表结构以及数据记录

--------------------------------

大文本以及延迟加载等注解的使用

    //大文本类型   例如个人信息说明
private String info;
//大文本类型 文件
private Byte[] file;
//图片路径 //需求:该字段不作为持久化字段 使用@Transient
private String imgpath; //大文本类型 如果没有特殊的表明 那么默认255长度 不能满足需求
//使用该注解的话String类型映射到数据库的类型为: Byte类型映射到数据库中的类型为:
@Lob
public String getInfo() {
return info;
} public void setInfo(String info) {
this.info = info;
}
//该字段内容在执行查询的时候 按需加载
@Lob @Basic(fetch=FetchType.LAZY)
public Byte[] getFile() {
return file;
} public void setFile(Byte[] file) {
this.file = file;
}
@Transient
public String getImgpath() {
return imgpath;
} public void setImgpath(String imgpath) {
this.imgpath = imgpath;
}

------------------------------------------

查询测试

为了方便观察,我们让查询的sql语句在控制台中打印,在persistence.xml配置如下内容:

 <!-- 配置控制台打印sql -->
<property name="hibernate.show_sql" value="true"/>
<!-- sql语句格式化配置 -->
<property name="hibernate.format_sql" value="true"/>

测试1:

//查询测试1
@Test
public void getPerson1() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
System.out.println("---------------0");
Person p = em.find(Person.class,1);//相当于hibernate中的get方法
System.out.println("---------------1");
em.close();
System.out.println("---------------2");
System.out.println(p.getName());
}

测试2:

//查询测试2
@Test
public void getPerson2() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
//相当于hibernate中的load方法
System.out.println("---------------0");
Person p = em.getReference(Person.class,1);//该方法和find方法的不同再于:第一次访问对象中的属性时才会发生数据的装载行为
System.out.println("---------------1");
System.out.println(p.getName());
System.out.println("---------------2");
//但是必须保证EntityManager没有关闭
em.close();
factory.close();
}

使用该方法时,如果是第一次加载对象属性,那么EntityManager不能关闭  否则异常

    //查询测试2
@Test
public void getPerson2() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
//相当于hibernate中的load方法
System.out.println("---------------0");
Person p = em.getReference(Person.class,1);//该方法和find方法的不同再于:第一次访问对象中的属性时才会发生数据的装载行为
System.out.println("---------------1");
//System.out.println(p.getName());
//System.out.println("---------------2");
//但是必须保证EntityManager没有关闭
em.close();
factory.close();
//如果是第一次加载属性这里将报错:nosession异常
System.out.println(p.getName());
}

这两个方法如果在执行查询的时候,数据库中没有查询的对象时  产生的结果也不同  前者不会报异常,而后者会报

//异常测试  正常执行  输出null
Person p = em.find(Person.class,3);
System.out.println(p);
em.close();
factory.close();

正常执行,输出null(不是打印地址,这里需要注意,如果没有close语句的时候,则会打印对象地址,这个地方我也没有搞明白)

    //异常测试   出现异常  实体类找不到  而且出现异常的时机在输出p的时候产生  而不是在执行查询的时候产生
Person p = em.getReference(Person.class,3);//
System.out.println(p);//在执行该语句的时候 产生异常 而不是在查询的时候
em.close();
factory.close();

-----------------------------

更新测试

    //更新测试
@Test
public void updatePerson() {
//该方法中的参数就是配置文件中 持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();//开启事务
Person p = em.find(Person.class,1);//此时处于托管态
p.setName("xx3");
em.getTransaction().commit();//提交事务 此时会执行批处理程序 把数据更新到数据库 所以该语句很重要 不能省略
//em.close();
//factory.close();
}

介绍两个方法

第一个方法:

    //更新测试2
@Test
public void updatePerson2() {
//该方法中的参数就是配置文件中 持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();//开启事务
Person p = em.find(Person.class,1);//此时处于托管态
em.clear();//把实体管理器中的所有对象变成游离状态 然后此时更新就无法完成了
p.setName("xx4");
em.getTransaction().commit();//提交事务
}

控制台只有查询语句而没有更新语句

第二个方法:

    //更新测试2
@Test
public void updatePerson2() {
//该方法中的参数就是配置文件中 持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();//开启事务
Person p = em.find(Person.class,1);//此时处于托管态
em.clear();//把实体管理器中的所有对象变成游离状态 然后此时更新就无法完成了
p.setName("xx5");
em.merge(p);//用于把游离状态的更新同步回数据库
em.getTransaction().commit();//提交事务
}

控制台打印:

Hibernate:
select
person0_.id as id1_0_0_,
person0_.birthday as birthday2_0_0_,
person0_.file as file3_0_0_,
person0_.gender as gender4_0_0_,
person0_.info as info5_0_0_,
person0_.personname as personna6_0_0_
from
Person person0_
where
person0_.id=?
Hibernate:
select
person0_.id as id1_0_0_,
person0_.birthday as birthday2_0_0_,
person0_.file as file3_0_0_,
person0_.gender as gender4_0_0_,
person0_.info as info5_0_0_,
person0_.personname as personna6_0_0_
from
Person person0_
where
person0_.id=?
Hibernate:
update
Person
set
birthday=?,
file=?,
gender=?,
info=?,
personname=?
where
id=?

可以完成更新操作

----------------------------------------------------

删除测试

    //删除
@Test
public void deletePerson() {
//该方法中的参数就是配置文件中 持久化单元的名称
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();//开启事务
Person p = em.find(Person.class,1);//此时处于托管态
em.remove(p);
em.getTransaction().commit();//提交事务
}

完成删除

控制台打印:

Hibernate:
select
person0_.id as id1_0_0_,
person0_.birthday as birthday2_0_0_,
person0_.file as file3_0_0_,
person0_.gender as gender4_0_0_,
person0_.info as info5_0_0_,
person0_.personname as personna6_0_0_
from
Person person0_
where
person0_.id=?
Hibernate:
delete
from
Person
where
id=?

---------------------------------------------

 JPQL语句

--------------------------

HQL:https://www.imooc.com/article/15791

JQPL:https://blog.csdn.net/czp11210/article/details/50799489

查询测试:

EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
Query createQuery = em.createQuery("select a from Person a where a.id=:id");
createQuery.setParameter("id",1); List<Person> resultList =createQuery.getResultList();//这种返回结果可以允许查询的实体不存在
for(Person p:resultList) {
System.out.println(p.getName());
}

即使查询不到也没有关系 ,而下面的这种结果返回情况就不行了

Object singleResult = createQuery.getSingleResult();

如果查询的实体不存在  那么就如下:

--------------------------------

删除测试:

    //删除
@Test
public void delete() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
em.getTransaction().begin();
Query createQuery = em.createQuery("delete from Person where id=?1");
createQuery.setParameter(1,2);
createQuery.executeUpdate();
em.getTransaction().commit();
}

删除的对象不存在也没有关系

----------------------------------

更新:

//更新
@Test
public void update() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
em.getTransaction().begin();
//命名参数
Query createQuery = em.createQuery("update Person set name=:name where id=:id");
createQuery.setParameter("name","xx3");
createQuery.setParameter("id",3);
createQuery.executeUpdate(); //第二条更新语句 使用位置参数
createQuery = em.createQuery("update Person set name=?100 where id=?250");
createQuery.setParameter(100, "xx4");
createQuery.setParameter(250,4);
createQuery.executeUpdate(); em.getTransaction().commit();//提交事务 执行了两次更新
}

-------------------------------------

命名查询

实体类:

测试代码:

//命名查询  在实体上边直接写JPQL语句
@Test
public void update2() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
em.getTransaction().begin();
Query createNamedQuery = em.createNamedQuery("updateSiggle");
createNamedQuery.setParameter("name","fffff");
createNamedQuery.setParameter(1,4);
createNamedQuery.executeUpdate();
em.getTransaction().commit();//提交事务 执行了两次更新
}
@Test
public void execute() {
EntityManagerFactory factory=Persistence.createEntityManagerFactory("simple");
EntityManager em=factory.createEntityManager();
em.getTransaction().begin();
//执行查询
Query createNamedQuery = em.createNamedQuery("queryPersonById");
createNamedQuery.setParameter("id",4);
List<Person> resultList = createNamedQuery.getResultList();
for(Person p:resultList) {
System.out.println(p.getName());
}
//执行更新
Query createNamedQuery2 = em.createNamedQuery("updatePersonById");
createNamedQuery2.setParameter("name","hhhh");
createNamedQuery2.setParameter("id",4);
createNamedQuery2.executeUpdate();
em.getTransaction().commit();//提交事务 执行了两次更新
}

----------------------------

一对多

实体代码

order

package org.model;

import java.util.HashSet;
import java.util.Set; import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="orders")//因为在mysql中有关键字order 所以这里指定建立的表名称
public class Order{
private String orderid;
private Float amount=0f;
//创建多方属性
private Set<OrderItem> items=new HashSet<OrderItem>();
//fetch加载策略:懒加载 在一方配置时默认为此方式 可不写
//出现mappedBy时 表示该实体为被维护方 里边的属性名称表示:由OrderItem这个实体中的order属性来维护该关系
@OneToMany(cascade= {CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH,CascadeType.REMOVE}
,fetch=FetchType.LAZY,mappedBy="order")
public Set<OrderItem> getItems() {
return items;
}
public void setItems(Set<OrderItem> items) {
this.items = items;
} @Id @Column(length=12)
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
@Column(nullable=false)
public Float getAmount() {
return amount;
}
public void setAmount(Float amount) {
this.amount = amount;
}
//相互建立关联的过程
public void addOrderItem(OrderItem orderItem) {
orderItem.setOrder(this);
this.items.add(orderItem); } }

orderitem

package org.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import org.hibernate.boot.model.source.spi.CascadeStyleSource; //订单项实体
@Entity
public class OrderItem {
private Integer id;
private String productName;
private Float productPrice=0f;
//创建一方属性
private Order order;
//级联方式:选择级联更新 级联刷新 级联保存不需要:一般都是在保存订单的时候去保存订单项
//使用多对一注解的时候 默认加载方式为立即加载
//optional:表示该外键字段是否可以为空 true 反映在数据库中表示该字段允许为空 false表示该字段 不可以为空 必须存在
//JoinColumn指定生成的外键字段的名称
@ManyToOne(cascade= {CascadeType.MERGE,CascadeType.REFRESH},optional=false)
@JoinColumn(name="order_id")
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
@Id @GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(length=20,nullable=false)
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
@Column(nullable=false)
public Float getProductPrice() {
return productPrice;
}
public void setProductPrice(Float productPrice) {
this.productPrice = productPrice;
} }

测试类:

@Test
public void save() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
//创建订单对象
Order order=new Order();
order.setOrderid("123");
order.setAmount(123.3f);
//创建多个订单项对象
OrderItem orderItem1=new OrderItem();
orderItem1.setProductName("A商品");
orderItem1.setProductPrice(33.5f);
OrderItem orderItem2=new OrderItem();
orderItem2.setProductName("B商品");
orderItem2.setProductPrice(66f);
//需要相互建立关联 这个代码写在order实体中
/*
HashSet<OrderItem> hashSet=new HashSet<OrderItem>();
hashSet.add(orderItem1);
hashSet.add(orderItem2);
order.setItems(hashSet);
orderItem1.setOrder(order);
orderItem2.setOrder(order);
*/
order.addOrderItem(orderItem1);
order.addOrderItem(orderItem2);
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();//必须开启事务 否则无法保存
entityManager.persist(order);
//entityManager.merge(order);如果表中order记录已经存在 而订单项中的记录不存在 即使现在已经相互关联了
//但是调用persist方法的时候 订单项的数据并不会更新到数据库 因为只有调用merge时级联更新才会起作用
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

----------------------------

一对一

实体类代码

person

package org.OneToOne;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne; @Entity
public class Person {
private Integer pid;
private String pname;
//规定该实体作为外键的维护端
private Card card;
@Id @GeneratedValue
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
@Column(length=4,nullable=false)
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
//外键不能为空 外键名称card_id
@OneToOne(cascade={CascadeType.ALL},optional=false)
@JoinColumn(name="card_id")
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
} }

card

package org.OneToOne;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne; @Entity
public class Card {
private Integer cid;
private String code;
private Person person;
@Id @GeneratedValue
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
@Column(length=18,nullable=false)
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
//mappedBy指定关系的维护端为person card为被维护端 属性值表示 由Person这个实体中的card属性来维护该关系
//该实体是被维护端 主键在维护端person中 所以person表是参考该表中的主键 所以这个地方不用配置optional=false属性 也最好不要配置
@OneToOne(cascade= {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},mappedBy="card")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
} }

测试:

    //1对1 在配置文件中创建第二个持久化单元  使用新的数据库
@Test
public void save2() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple2");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
//创建对象
Person person=new Person();
person.setPname("张三");
Card card=new Card();
card.setCode("112254563");
person.setCard(card);//一对一的时候 不用互相关联 保存维护端的时候 被维护端可以通知时保存
entityManager.persist(person);
entityManager.getTransaction().commit();
entityManager.close();
}

--------

1-m
多的一方为关系维护端,关系维护端负责外键记录的更新(出现mappedBy时 表示该实体为被维护方),关系被维护端是没有权利更新外键记录
-----------------
级联类型:以下几种操作都是在执行实体管理器中封装的方法时才会执行的
CascadeType.REFRESH 级联刷新:在查询order的时候 对orderItem进行查询 在执行find时起作用
(在调用 object.reflush时才会触发的操作)
CascadeType.PERSIST 级联保存:在执行保存order的时候 同时执行orderItem对象的保存工作 (在执行persist方法时起作用)
CascadeTppe.MERGE 级联合并:在更新order的时候,同时更新orderItem对象 (在执行merge方法时起作用)
CascadeType.REMOVE 级联删除:没有主外键约束的情况下 在执行order删除的时候,同时执行orderItem对象的删除 否则不删除 (在执行romove方法时才起作用)
---------
以上4种级联可以使用:CascadeType.ALL代替
-----------------
一对多:在一方配置的时候 默认的延迟加载 在多方配置的时候,默认的是立即加载

--------------------
一对一:一对一的时候 不用互相关联 保存维护端的时候 被维护端可以同时进行保存

------

---------------------------------------

多对多

基本配置

实体类:

student:

@Entity
public class Student {
private Integer id;
private String name;
private Set<Teacher> teachers=new HashSet<Teacher>();
@Id @GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(length=10,nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//规定:学生为关系的维护端
//@JoinTable指定中间表的名称为t_s
@ManyToMany(cascade= {CascadeType.REFRESH})
@JoinTable(name="t_s")
public Set<Teacher> getTeachers() {
return teachers;
}
public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
} }

teacher:

@Entity
public class Teacher {
private Integer id;
private String name;
private Set<Student> students=new HashSet<Student>(); @Id @GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(length=10,nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(cascade= {CascadeType.REFRESH},mappedBy="teachers")
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
} }

建表测试:

EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
entityManagerFactory.close();

下面是所创建的数据库表:

如果不喜欢框架自动生成的字段名称,我们可以自己控制

在定义中间表的时候,加上如下属性:

//@JoinTable指定中间表的名称为t_s
//inverseJoinColumns关系被维护端teacher 在中间表将要对应的外键名称
//joinColumns关系维护端 即本类student 在中间表中将要对应的外键名称
@ManyToMany(cascade= {CascadeType.REFRESH})
@JoinTable(name="t_s",inverseJoinColumns=@JoinColumn(name="tid"),joinColumns=@JoinColumn(name="sid"))
public Set<Teacher> getTeachers() {
return teachers;
}

然后重新生成的表字段:

------------------------------------------------------------

插入数据:向student和teacher表中各插入一条记录

    //数据插入
@Test
public void insert() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
//创建对象
Student student=new Student();
student.setName("肖战");
Teacher teacher=new Teacher();
teacher.setName("张老师");
//保存
entityManager.persist(student);
entityManager.persist(teacher);
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

数据库:

目前中间表是没有数据的,现在进行2个对象之间的关联,然后向中间表插入数据(建立关系,即插入数据)

插入之前,为了更加方便的建立和解除关系,所以我们在student方(关系维护方,增加如下代码)

   public void addTeacher(Teacher teacher) {
this.teachers.add(teacher);
}
public void removeTeacher(Teacher teacher) {
/*if(this.teachers.contains(teacher)) {//
this.teachers.remove(teacher);
}*/
//如果集合中没有 不移除 不会报错
this.teachers.remove(teacher);
}

如下是添加记录的测试类:

    @Test
public void update() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
//得到对象
Student student = entityManager.getReference(Student.class,3);
Teacher teacher = entityManager.getReference(Teacher.class,4);
//建立关系
student.addTeacher(teacher);
//建立了关系 提交之后 自动向中间表插入一条数据
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

现在开始解除关系,即删除中间表的数据:

测试类:

@Test
public void remove() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
//找出两个需要解除关系的对象
Student student = entityManager.getReference(Student.class,3);
Teacher teacher = entityManager.getReference(Teacher.class,4);
//调用的是已经定义好的方法 解除关系
student.removeTeacher(teacher);
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

可以看到解除关系之后,执行代码,中间表的数据已经被删除

----------------------

思考:当中间表数据存在时,删除teacher对象 ,是否可以删除成功

【不可以,因为存在外键约束,所以在删除中间表数据之后,才能删除老师对象

删除老师 (注意老师是被维护端 所以没有权利删除外键的记录 即中间表的数据 )
如果非要删除 那么必须删除中间表数据(解除关系) 然后删除老师】

先看有问题的代码,直接删老师对象,如下:

    @Test
public void removeTeacher() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Teacher teacher = entityManager.getReference(Teacher.class,4);
entityManager.remove(teacher);
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

提示,存在外键约束,不能正常删除

下面是正确的代码:

    @Test
public void removeTeacher() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Student student = entityManager.getReference(Student.class,3);
Teacher teacher = entityManager.getReference(Teacher.class,4);
//先解除关系
student.removeTeacher(teacher);
//然后执行删除
entityManager.remove(teacher);
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

这样就删除成功了

---------------------------------------

删除学生对象,可以直接进行删除,因为该对象是关系维护端,有对中间表进行操作的权限,所以在执行删除的时候,是先删除中间表,然后删除学生

    //删除学生
public void removeStudent() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Student student = entityManager.getReference(Student.class,3);
//删除学生
entityManager.remove(student);
entityManager.getTransaction().commit();
entityManagerFactory.close();
}

删除了学生表中的对象,以及相关的中间表的数据

-------------------------

联合主键

联合主键类:AirLinePK

package org.model.pk;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable; //复合主键类
//有3个要求:1.必须提供无参的构造方法 2.实现序列化接口 3.覆写equals和hashCode方法
@Embeddable
public class AirLinePK implements Serializable{
private String start;
private String end;
@Column(length=10)
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
@Column(length=10)
public String getEnd() {
return end;
}
public void setEnd(String end) {
this.end = end;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
} public AirLinePK(String start, String end) {
super();
this.start = start;
this.end = end;
} }

AirLine类中的主键是上边的联合主键

package org.model.pk;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity; @Entity
public class AirLine {
//联合主键
private AirLinePK id;
private String name; public AirLine(AirLinePK id, String name) {
super();
this.id = id;
this.name = name;
} //标识复合主键的注解
@EmbeddedId
public AirLinePK getId() {
return id;
}
public void setId(AirLinePK id) {
this.id = id;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} }

测试:

    //联合主键测试
@Test
public void build() {
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("simple2");
EntityManager createEntityManager = entityManagerFactory.createEntityManager();
//开启事务
createEntityManager.getTransaction().begin();
//创建对象
AirLinePK airLinePK=new AirLinePK("北京","上海");
AirLine airline=new AirLine(airLinePK,"北京飞往上海");
createEntityManager.persist(airline);
//提交事务
createEntityManager.getTransaction().commit();
}

数据库:

----------------------------------------------

继承注解配置  

参考博客:http://cjnetwork.iteye.com/blog/974686

多方:Employee是父类,他有两个子类Sales,Skiller   一方:Department

Employee:

package org.model;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.swing.text.IconView; import org.hibernate.annotations.ManyToAny;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)//映射类型:单表 即所以继承的子类字段都在一个表中 默认此方式
@DiscriminatorColumn(name="type")//鉴别器的列
//:区别不同的类 因为存在Employee Sales Skiller的数据将来都会存入employee表 区别某条数据到底是哪个类的对象
@DiscriminatorValue("0")//鉴别器的值
public class Employee {
private int id;
private String name;
private Department department;
@Id @GeneratedValue()
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=10,nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne()
//@JoinColumn(name="depart_id")//外键名 不指定的情况下 默认: 字段名_id
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
} }

Sales:

package org.model;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity; @Entity
@DiscriminatorValue("2")//鉴别器的值
public class Sales extends Employee {
private int sell;//出售额 public int getSell() {
return sell;
} public void setSell(int sell) {
this.sell = sell;
} }

Skiller:

package org.model;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity; @Entity
@DiscriminatorValue("3")//鉴别器的值
public class Skiller extends Employee {
private String Skill;//技能 public String getSkill() {
return Skill;
} public void setSkill(String skill) {
Skill = skill;
} }

Department:

package org.model;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Department {
private int id;
private String name;
//private Set<Employee> emps=new HashSet<Employee>();
private Set<Employee> emps;
@Id @GeneratedValue()
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=10)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(cascade= {CascadeType.MERGE,CascadeType.PERSIST},fetch=FetchType.LAZY,mappedBy="department")//mappedBy出现在该类,表示该类为关系被维护方
public Set<Employee> getEmps() {
return emps;
}
public void setEmps(Set<Employee> emps) {
this.emps = emps;
} }

测试:

public void t1() {
EntityManager em = rtn();
Department department=new Department();
department.setName("销售部"); Employee e1=new Employee();
e1.setName("张");
e1.setDepartment(department); //创建employee的子类对象
Sales e2=new Sales();
e2.setName("王");
e2.setSell(10);
e2.setDepartment(department); Skiller e3=new Skiller();
e3.setName("孙");
e3.setSkill("会唱歌");
e3.setDepartment(department); //创建员工集合
Set<Employee> emps=new HashSet<Employee>();
emps.add(e1);
emps.add(e2);
emps.add(e3);
//互相关联 添加进部门实体中
department.setEmps(emps); em.getTransaction().begin();
em.persist(department);
em.getTransaction().commit();
}

数据库:

---------------------------------

JPA学习(基于hibernate)的更多相关文章

  1. JPA学习---第一节:JPA详解

    一.详解 JPA JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据.他的出现主要是 ...

  2. JPA学习笔记

    一.JPA基础1.1 JPA基础JPA: java persistence api 支持XML.JDK5.0注解俩种元数据的形式,是SUN公司引入的JPA ORM规范 元数据:对象和表之间的映射关系 ...

  3. 再谈Hibernate级联删除——JPA下的Hibernate实现一对多级联删除CascadeType.DELETE_ORPHAN

    声明: 1.本文系原创,非抄袭或转载过来的. 2.本文论点都亲手做过实验论证. 3.本文所讲的Hibernate配置都基于注解的方式,hbm语法未提供. 非常多人对持久层概念搞不清JPA.Hibern ...

  4. Spring学习---JPA学习笔记

    用了一段时间的Spring,到现在也只是处于会用的状态,对于深入一点的东西都不太了解.所以决定开始深入学习Spring. 本文主要记录JPA学习.在学习JPA之前,需要了解一些ORM的概念. ORM概 ...

  5. JPA学习(六、JPA_JPQL)

    框架学习之JPA(六) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...

  6. JPA学习(五、JPA_二级缓存)

    框架学习之JPA(五) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...

  7. JPA学习(三、JPA_API)

    框架学习之JPA(三) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...

  8. JPA学习(一、JPA_Hello World)

    框架学习之JPA(一) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 ...

  9. JPA学习笔记1——JPA基础

    1.JPA简介: Java持久化规范,是从EJB2.x以前的实体Bean(Entity bean)分离出来的,EJB3以后不再有实体bean,而是将实体bean放到JPA中实现.JPA是sun提出的一 ...

随机推荐

  1. bzoj1106

    模拟+树状数组 先开始以为是先删距离最小的,这样可以减小上下的距离,然后觉得很难写,看码长很短,就看了题解,结果很奥妙 我们只考虑两种元素,就是如果像-a-b-a-b-这样的肯定得交换,如果像-a-b ...

  2. 使用GitHub(转载)

    转自:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/00137628548491 ...

  3. php验证手机号是否合法

    用正则匹配手机号码的时候, 我们先分析一下手机号码的规律: 1. 手机号通常是11位的 2. 经常是1开头 3. 第二个数字通常是34578这几个数字, 2014.5.5日170号段的手机号开卖所以这 ...

  4. P3390矩阵快速幂

    题目背景 矩阵快速幂 题目描述 给定n*n的矩阵A,求A^k 输入输出格式 输入格式: 第一行,n,k 第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素 输出格式: 输出A^k ...

  5. [Swift通天遁地]四、网络和线程-(9)上传图片并实时显示上传进度

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. HTTP Status 500 - Could not write content: could not initialize proxy - no Session

    分析出现no Session错误的原因以及给出解决方案: 使用SpringMVC + JSON数据返回时,经常会出现no Session的错误: 报错原因:因为懒加载在提取关联对象的属性值的时候发现E ...

  7. 零基础如何学习Java和web前端

    今天说一下零基础到底能不能学习Java,为什么有的人说学不了呢,那么接下来我为大家揭晓,零基础到底适合不适合学习Java. 零基础学习Java的途径第一个就是看视频,然后就是看书,或者在线下报个培训班 ...

  8. $ST表刷题记录$

    \(st表的题目不太多\) 我做过的就这些吧. https://www.luogu.org/problemnew/show/P3865 https://www.luogu.org/problemnew ...

  9. python自动化测试学习笔记-5常用模块

    上一次学习了os模块,sys模块,json模块,random模块,string模块,time模块,hashlib模块,今天继续学习以下的常用模块: 1.datetime模块 2.pymysql模块(3 ...

  10. JavaScript 计时器

    在JavaScript中,我们可以在设定的时间间隔之后来执行代码,而不是在函数被调用后立即执行.计时器类型:一次性计时器:仅在指定的延迟时间之后触发一次.间隔性触发计时器:每隔一定的时间间隔就触发一次 ...