參考博客:http://www.javashuo.com/article/p-shtmciay-dd.htmlhtml
經常使用註解:java
https://blog.csdn.net/eastlift/article/details/2463243mysql
http://www.javashuo.com/article/p-rknybqru-hw.htmlsql
https://blog.csdn.net/u014421556/article/details/52040263數據庫
----------------------session
所需jarapp
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&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&characterEncoding=UTF-8" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="jay571018"></property> --> </properties> </persistence-unit> </persistence>
---------------------------------------ide
實體類: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(); }
數據庫:
---------------------------------