摘要:說明首先來說是一個持久化規范,也就是說當我們用的時候我們不需要去選面向的編程了,這樣就大大降低了偶和度了引入是一種規范,那么它的編程有哪些要求呢引入下載的包導入文件夾,然后我們的在下面加上一個目錄在該文件夾下面加上一個文件,這個文件的規范
說明
首先來說JPA是一個持久化規范,也就是說當我們用jpa的時候我們不需要去選面向hibernate的api編程了,這樣就大大降低了偶和度了
引入JPA是一種規范,那么它的編程有哪些要求呢?
引入下載的jar包導入lib文件夾,然后我們的在src下面加上一個META-INF目錄在該文件夾下面加上一個persistence.xml文件,這個文件的規范寫法
org.hibernate.ejb.HibernatePersistence ????
這個文件中的寫話我們可以再hibernate的jpa實現包里面找到對應的例子,這里我是使用的是hibernate來實現JPA實現,上面的配置也都和heibernate差不太多值得注意的:
Persistence-unit持久性化單元,我們可以隨便命名但是在后面回到他的,通過它來找到相關的配置信息
transaction-type 是指事物的類型,在通常情況下我們是本地的,但是當我們遇到兩個數據庫保存的時候 我們會到到JTA事物來控制事務,也就是二次提交
實體類來映射數據表Persion.java
@Entity //就是告訴JPA我是一個實體bean @Table(name="t_person")//作為修改表名,默認情況是類名 public class Person { /** * GenerationType.AUTO它會根據數據庫方言來選擇正確的生成策略 * 默認情況下就是AUTO */ @Id//映射主鍵 @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; // 映射一列到數據庫中 length是指字段的長度 // nullable是指是否為空,默認情況是空 // 當我們不想讓類字段名與數據庫名一樣的時候用到的 @Column(length=10,nullable=false,name="personname") private String name; // 映射日期類型TemporalType有好幾種映射方式 // 我們可以根據自己的需求選擇正確的映射方式 @Temporal(TemporalType.DATE) ?@Column(nullable=false) private Date birthday; // 用枚舉類型來映射性別EnumType有好幾種映射方式 // 這里使用的是枚舉的String類型,我們也一個選擇枚舉的索引 @Enumerated(EnumType.STRING) @Column(nullable=false,length=5) private Sex sex = Sex.MEN; ?// 對應大文本和圖片就是二進制 @Lob private String info; // 支持延遲加載(減少內存的消耗) @Lob @Basic(fetch=FetchType.LAZY) private Byte[] image; // 不想這個字段與數據庫表映射 @Transient private String imagepath; // 版本標識 防止臟讀 @Version private Integer version; // get set // }利用jpa來操作數據庫
Test.java
@Test public void testSave() { /** * jun是在persistence.xml中持久化單元名稱 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); //--->>SessionFactory-->>session-->>begin EntityManager em = factory.createEntityManager(); em.getTransaction().begin();//開啟事物 Person person = new Person("劉文軍"); person.setBirthday(new Date()); em.persist(person); System.out.println("----->>"+person.getSex().getName()); em.getTransaction().commit(); em.close(); factory.close(); }
這里我們EntityManagerFactory就相當于Hibernate中的SessionFactory,
然而EntityManager就相當于Hibernate中的Session。
在JPA中我們獲得它的方式是Persistence.createEntityManagerFactory("jun");
jun是在persistence.xml中持久化單元名稱
EntityManager em = factory.createEntityManager();
其中EntityManager中的幾種操作數據庫方法有
Persist(),find(),getReference(),merge(),remove()這里我就列出幾種常見的
這里說有的getReference()就相當于Hibernate中的Load() 支持Lazy加載,
getReference它會查找一個代理對象,當訪問它的屬性的時候它才會向數據庫操作
但是值得注意的這個必須確保Session是打開狀態
實體bean的幾種狀態 一、新建狀態new一個實體的時候它所處于的狀態
二、托管狀態這個狀態非常重要,當一個實體bean是托管狀態的時候我們修改它的屬性值得話,即使我們沒有用到hibernate中的相關方法操作數據庫,她也會同步到數據庫里的,托管就是從數據庫里面查詢到的一個對象,記住,托管狀態必須的和事物關聯上來
em.getTransaction().begin(); person.setName("小劉"); em.getTransaction().commit(); em.close(); factory.close();三、游離狀態
當我們使用EntityManager中的clear()方法的時候,它會把事物管理器中的所有實體變成游離狀態,
處在游離狀態的實體bean,我們修改它的屬性它不會同步到數據庫中的
em.getTransaction().begin(); em.clear(); // 把實體管理器中的所有實體都變成游離狀態 person.setName("老劉"); em.merge(person); em.getTransaction().commit(); em.close(); factory.close();四、關閉狀態
就是當我們把Session關閉的時候,實體bean處于的狀態
JPA中使用EJQL語句 查詢public void query() { /** * jun是在persistence.xml中持久化單元名稱 */ EntityManagerFactory factory=Persistence.createEntityManagerFactory("jun"); //--->>SessionFactory-->>session-->>begin EntityManager em = factory.createEntityManager(); Query query = em.createQuery("select o from Person o where o.id=?1"); query.setParameter(1, 2); // /** * Person person = (Person)query.getSingleResult(); * 這個就相當于Hibernate中的uniqueResult(); * 如果沒有查詢到數據的話會出錯的,所有我們一般不這樣做 * 我們先得到List 然后遍歷它 */ List刪除查詢(記得要開啟事物)list = query.getResultList(); for(Person person : list) System.out.println("---------->>" + person.getName()); query = em.createQuery("select count(o) from Person o "); Long count = (Long)query.getSingleResult(); System.out.println("---------->>" + count); em.close(); factory.close(); }
public void deletequery() { /** * jun是在persistence.xml中持久化單元名稱 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query = em.createQuery("delete from Person o where o.id=?1"); query.setParameter(1, 2); query.executeUpdate(); em.getTransaction().commit(); em.close(); factory.close(); }修改查詢(記得要開啟事物)
public void updatequery() { /** * jun是在persistence.xml中持久化單元名稱 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query = em.createQuery("update from Person o set o.name=:name where o.id=:id"); query.setParameter("name", "小劉"); query.setParameter("id", 3); query.executeUpdate(); em.getTransaction().commit(); em.close(); factory.close(); }刷新方法
public void testgetPerson() { /** * jun是在persistence.xml中持久化單元名稱 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); //--->>SessionFactory-->>session-->>begin EntityManager em = factory.createEntityManager(); Person person = em.find(Person.class, 1); /** * 1分鐘內 * 比方說這里有人直接操作數據庫改了數據,我們如何來得到person呢 * 有人說我們可以再執行一下find方法,這個事不可以的,因為你再次 * 執行find方法的時候EntityManager會中一級緩存中取得id是1的 * Person數據,也就是說不能得到最新的數據,那么如果我們想得到最 * 新的數據怎么辦呢?JPA幫我們做了一個刷新的方法em.refresh(person); * 通過它我們就可以得到最新的數據了 */ em.refresh(person); System.out.println("----->>"+person.getName()); em.close(); factory.close(); }JPA中實現表間關聯關系 一的多
@Entity @Table(name="t_order") public class Order { ????@Id ????@Column(length=200) ????private String orderid; ????@Column(nullable=false) ????private Float amount = 0f; ????/** ???? * cascade=CascadeType.REFRESH設置級聯刷新 ???? * CascadeType.PERSIST設置級聯保存 ???? * CascadeType.MERGE設置級聯更新 ???? * CascadeType.REMOVE設置級聯刪除 ???? * CascadeType.ALL設置四種級聯 ???? * 這四種級聯都是對應的四種方法才能起作用PERSIST(),MERGE(),REMOVE(),REFRESH() ???? * fetch=FetchType.LAZY支持LAzy加載,只有用到該屬性的時候才會讀集合數據 ???? * 注意這時我們必須保持EntityManager是開著的,默認是延遲加載 ???? * mappedBy="order"指定OrderItem類里面的order這個屬性來維護關系 ???? */ ????@OneToMany(cascade={CascadeType.ALL}, ????????????????????fetch=FetchType.LAZY, ????????????????????mappedBy="order") private Setitems = new HashSet (); // get set // }
為了我們添加Set集合方便我們通常的情況下我們的寫一個添加Set的方法
public void addOrderItem(OrderItem orderItem) { orderItem.setOrder(this);//this就是Order items.add(orderItem); }多的一
@Entity @Table(name="t_orderitem") public class OrderItem { ????@Id ????@GeneratedValue ????private Integer id; ????@Column(length=40,nullable=false) ????private String productName; ????@Column(nullable=false) ????private Float sellPrice = 0f; ????/** ???? * optional=false指定該字段不能空 ???? * @JoinColumn(name="order_id")指明關聯關系的子段名 ???? * 即定義外鍵的名稱 ???? * ? ???? * */ ????@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false) ????@JoinColumn(name="order_id") private Order order; // get set // }測試
public void testCreate() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Order order = new Order(); order.setAmount(598f); order.setOrderid(UUID.randomUUID().toString()); OrderItem orderItem1 = new OrderItem(); orderItem1.setProductName("籃球"); orderItem1.setSellPrice(256f); order.addOrderItem(orderItem1); OrderItem orderItem2 = new OrderItem(); orderItem2.setProductName("女人"); orderItem2.setSellPrice(800000f); order.addOrderItem(orderItem2); em.persist(order); em.getTransaction().commit(); em.close(); factory.close(); }
這里我們并沒有保存orderIterm
但是我們在數據庫中依然能看到orderIterm的數據
保存到數據庫里面了,這里就是設置級聯保存的緣故
CascadeType.PERSIST設置級聯保存
Person.java
@Entity @Table(name="t_person") public class Person { ????@Id ????@GeneratedValue private Integer id; ????@Column(length=10,nullable=false) private String name; ????@OneToOne(optional=false,cascade={CascadeType.ALL}) ????@JoinColumn(name="idcard_id") private IDCard idCard; public Person() {} ????public Person(String name) { ????????this.name = name; } }
IDCard.java
@Entity @Table(name="t_idcard") public class IDCard { ????@Id ????@GeneratedValue private Integer id; ????@Column(length=18,nullable=false) private String cardno ; ????@OneToOne(mappedBy="idCard", ????????????cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE}) private Person person; public IDCard() {} ????public IDCard(String cardno) { this.cardno = cardno; } }測試
public void testCreateTable() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person person = new Person("小劉"); IDCard idCard = new IDCard("411521198409131915"); idCard.setPerson(person); person.setIdCard(idCard); em.persist(person); em.getTransaction().commit(); em.close(); factory.close(); }多對多
Student.java
@Entity @Table(name="t_student") public class Student { ????@Id ????@GeneratedValue ????private Integer id; ????@Column(length=10,nullable=false) ????private String name; ????/** ???? * @JoinTable(name="t_stu_tea", ????????????joinColumns=@JoinColumn(name="student_id"), ????????????inverseJoinColumns=@JoinColumn(name="teacher_id")) ????????創建中間表來維護兩個表的關系 ???? * joinColumns=@JoinColumn(name="student_id")定義維護端在中間表中的關聯字段 ???? * inverseJoinColumns=@JoinColumn(name="teacher_id")定義被維護端在中間表中的關聯字段 ???? * ???? */ ????@ManyToMany(cascade=CascadeType.REFRESH) ????@JoinTable(name="t_stu_tea", ????????????joinColumns=@JoinColumn(name="student_id"), ????????????inverseJoinColumns=@JoinColumn(name="teacher_id")) ????private Setteachers = new HashSet (); ????public Student() {} ????public Student(String name) { ????????this.name = name; } }
我們通常把set集合方法重寫
public void addTeacher(Teacher teacher) { this.teachers.add(teacher); } public void removeTeacher(Teacher teacher) { if(this.teachers.contains(teacher)) { this.teachers.remove(teacher); } }
Teacher.java
@Entity @Table(name="t_teacher") public class Teacher { ????@Id ????@GeneratedValue private Integer id; ????@Column(length=12,nullable=false) private String name; ????@ManyToMany(cascade=CascadeType.REFRESH,mappedBy="teachers") private Set測試students = new HashSet (); public Teacher() {} ????public Teacher(String name) { ????????this.name = name; } }
@Test public void testCreateTable() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = new Student("小劉"); Teacher teacher = new Teacher("肖老師"); em.persist(student); em.persist(teacher); em.getTransaction().commit(); em.close(); factory.close(); } /** * 建立學生跟老師的關系 */ @Test public void buildTS() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 1); student.addTeacher(em.getReference(Teacher.class, 1)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 解除學生跟老師的關系 */ @Test public void deleteTS() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 1); student.removeTeacher(em.getReference(Teacher.class, 1)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 刪除老師 */ @Test public void deleteTeacher() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); /** * 刪除老師的時候一定的解除掉老師和學生的關系 */ Student student = em.find(Student.class, 1); student.removeTeacher(em.getReference(Teacher.class, 1)); em.remove(em.getReference(Teacher.class, 1)); em.getTransaction().commit(); em.close(); factory.close(); } /** *刪除學生 */ @Test public void deleteStudent() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); /** * 這個為什么不需要解除關系呢,主要是因為學生這一段是維護端 */ Student student = em.find(Student.class, 1); em.remove(student); em.getTransaction().commit(); em.close(); factory.close(); }聯合主鍵
我們多帶帶寫一個類作為主鍵,但是這個類的要滿足3條規則
它必須實現Serializable接口
它必須重寫字段的hashCode()和equals()方法
要在類上表明@Embeddable,這個注解的意思就是讓它的屬性在AirLine也正常做屬性
那么我們在主體類里面用這個主鍵類做為id,在id上面加上@EmbeddedId表明就是用主鍵類的屬性作為主鍵,并映射到數據庫表中
AirLine.java
@Entity @Table(name="t_airline") public class AirLine { ????@EmbeddedId ????private AirLinePK id; ????@Column(length=10,nullable=false) private String name; }
AirLinePK.java
@Embeddable public class AirLinePK implements Serializable{ // 序列UID ????private static final long serialVersionUID = -7125628704970675246L; ????@Column(length=20) ????private String startLine; ????@Column(length=20) ????private String endLine; // 注意這里一定的時間他HashCode()和equals()方法 }測試
public void testPK() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); AirLine airLine = new AirLine("PEK","SHG","北京飛往上海"); em.persist(airLine); em.getTransaction().commit(); em.close(); factory.close(); }使用Spring Boot 配置
使用步驟類似上面介紹,關鍵是要理解一對一、一對多、多對一、多對多的關聯關系
引入jpa yml文件org.springframework.boot spring-boot-starter-data-jpa
# maven打包 clean compile package spring: # 熱重啟 devtools: restart: enabled: true # 數據源 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///qnzf?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false username: root password: # JPA配置 jpa: show-sql: true hibernate: naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl ddl-auto: update # tomcat server: port: 8080 tomcat: Uri-encoding: UTF-8實體類映射數據表
LED.java
@Entity @Table(name = "tbl_led") public class LED { public LED() { super(); } // 指定id @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 唯一鍵 @Column(unique = true) private Integer pin; // LED連接的針腳位 // 單向一對一 @OneToOne() @JoinColumn(name = "ledtype_id") private LEDType ledType; }使用jpa接口方法
LEDRepository.java
public interface LEDRepository extends JpaRepositorymvc中使用{ }
@Autowired private LEDPowerRepository ledPowerRepository;個別使用方法可以瀏覽其他教程介紹加強一下
Spring For All 社區 Spring Data JPA 從入門到進階系列教程
SpringBoot實戰SpringDataJPA
使用 Spring Data JPA 簡化 JPA 開發
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71560.html
摘要:一從零搭建環境本次我使用的是編輯器來搭建和環境首先,我們在新建項目的時候,選擇,然后就行了。可以看出,本次的版本為。這是一個非常好用的插件,有了它我們可以不用寫繁瑣的方法。非常適合我們做一些簡答的測試和小功能。 前言 只有光頭才能變強。 文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家對SpringB...
閱讀 821·2023-04-26 00:37
閱讀 706·2021-11-24 09:39
閱讀 2132·2021-11-23 09:51
閱讀 3767·2021-11-22 15:24
閱讀 733·2021-10-19 11:46
閱讀 1868·2019-08-30 13:53
閱讀 2409·2019-08-29 17:28
閱讀 1314·2019-08-29 14:11