摘要:說明首先來說是一個(gè)持久化規(guī)范,也就是說當(dāng)我們用的時(shí)候我們不需要去選面向的編程了,這樣就大大降低了偶和度了引入是一種規(guī)范,那么它的編程有哪些要求呢引入下載的包導(dǎo)入文件夾,然后我們的在下面加上一個(gè)目錄在該文件夾下面加上一個(gè)文件,這個(gè)文件的規(guī)范
說明
首先來說JPA是一個(gè)持久化規(guī)范,也就是說當(dāng)我們用jpa的時(shí)候我們不需要去選面向hibernate的api編程了,這樣就大大降低了偶和度了
引入JPA是一種規(guī)范,那么它的編程有哪些要求呢?
引入下載的jar包導(dǎo)入lib文件夾,然后我們的在src下面加上一個(gè)META-INF目錄在該文件夾下面加上一個(gè)persistence.xml文件,這個(gè)文件的規(guī)范寫法
org.hibernate.ejb.HibernatePersistence ????
這個(gè)文件中的寫話我們可以再hibernate的jpa實(shí)現(xiàn)包里面找到對應(yīng)的例子,這里我是使用的是hibernate來實(shí)現(xiàn)JPA實(shí)現(xiàn),上面的配置也都和heibernate差不太多值得注意的:
Persistence-unit持久性化單元,我們可以隨便命名但是在后面回到他的,通過它來找到相關(guān)的配置信息
transaction-type 是指事物的類型,在通常情況下我們是本地的,但是當(dāng)我們遇到兩個(gè)數(shù)據(jù)庫保存的時(shí)候 我們會(huì)到到JTA事物來控制事務(wù),也就是二次提交
實(shí)體類來映射數(shù)據(jù)表Persion.java
@Entity //就是告訴JPA我是一個(gè)實(shí)體bean @Table(name="t_person")//作為修改表名,默認(rèn)情況是類名 public class Person { /** * GenerationType.AUTO它會(huì)根據(jù)數(shù)據(jù)庫方言來選擇正確的生成策略 * 默認(rèn)情況下就是AUTO */ @Id//映射主鍵 @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; // 映射一列到數(shù)據(jù)庫中 length是指字段的長度 // nullable是指是否為空,默認(rèn)情況是空 // 當(dāng)我們不想讓類字段名與數(shù)據(jù)庫名一樣的時(shí)候用到的 @Column(length=10,nullable=false,name="personname") private String name; // 映射日期類型TemporalType有好幾種映射方式 // 我們可以根據(jù)自己的需求選擇正確的映射方式 @Temporal(TemporalType.DATE) ?@Column(nullable=false) private Date birthday; // 用枚舉類型來映射性別EnumType有好幾種映射方式 // 這里使用的是枚舉的String類型,我們也一個(gè)選擇枚舉的索引 @Enumerated(EnumType.STRING) @Column(nullable=false,length=5) private Sex sex = Sex.MEN; ?// 對應(yīng)大文本和圖片就是二進(jìn)制 @Lob private String info; // 支持延遲加載(減少內(nèi)存的消耗) @Lob @Basic(fetch=FetchType.LAZY) private Byte[] image; // 不想這個(gè)字段與數(shù)據(jù)庫表映射 @Transient private String imagepath; // 版本標(biāo)識(shí) 防止臟讀 @Version private Integer version; // get set // }利用jpa來操作數(shù)據(jù)庫
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就相當(dāng)于Hibernate中的SessionFactory,
然而EntityManager就相當(dāng)于Hibernate中的Session。
在JPA中我們獲得它的方式是Persistence.createEntityManagerFactory("jun");
jun是在persistence.xml中持久化單元名稱
EntityManager em = factory.createEntityManager();
其中EntityManager中的幾種操作數(shù)據(jù)庫方法有
Persist(),find(),getReference(),merge(),remove()這里我就列出幾種常見的
這里說有的getReference()就相當(dāng)于Hibernate中的Load() 支持Lazy加載,
getReference它會(huì)查找一個(gè)代理對象,當(dāng)訪問它的屬性的時(shí)候它才會(huì)向數(shù)據(jù)庫操作
但是值得注意的這個(gè)必須確保Session是打開狀態(tài)
實(shí)體bean的幾種狀態(tài) 一、新建狀態(tài)new一個(gè)實(shí)體的時(shí)候它所處于的狀態(tài)
二、托管狀態(tài)這個(gè)狀態(tài)非常重要,當(dāng)一個(gè)實(shí)體bean是托管狀態(tài)的時(shí)候我們修改它的屬性值得話,即使我們沒有用到hibernate中的相關(guān)方法操作數(shù)據(jù)庫,她也會(huì)同步到數(shù)據(jù)庫里的,托管就是從數(shù)據(jù)庫里面查詢到的一個(gè)對象,記住,托管狀態(tài)必須的和事物關(guān)聯(lián)上來
em.getTransaction().begin(); person.setName("小劉"); em.getTransaction().commit(); em.close(); factory.close();三、游離狀態(tài)
當(dāng)我們使用EntityManager中的clear()方法的時(shí)候,它會(huì)把事物管理器中的所有實(shí)體變成游離狀態(tài),
處在游離狀態(tài)的實(shí)體bean,我們修改它的屬性它不會(huì)同步到數(shù)據(jù)庫中的
em.getTransaction().begin(); em.clear(); // 把實(shí)體管理器中的所有實(shí)體都變成游離狀態(tài) person.setName("老劉"); em.merge(person); em.getTransaction().commit(); em.close(); factory.close();四、關(guān)閉狀態(tài)
就是當(dāng)我們把Session關(guān)閉的時(shí)候,實(shí)體bean處于的狀態(tài)
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(); * 這個(gè)就相當(dāng)于Hibernate中的uniqueResult(); * 如果沒有查詢到數(shù)據(jù)的話會(huì)出錯(cuò)的,所有我們一般不這樣做 * 我們先得到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分鐘內(nèi) * 比方說這里有人直接操作數(shù)據(jù)庫改了數(shù)據(jù),我們?nèi)绾蝸淼玫絧erson呢 * 有人說我們可以再執(zhí)行一下find方法,這個(gè)事不可以的,因?yàn)槟阍俅? * 執(zhí)行find方法的時(shí)候EntityManager會(huì)中一級(jí)緩存中取得id是1的 * Person數(shù)據(jù),也就是說不能得到最新的數(shù)據(jù),那么如果我們想得到最 * 新的數(shù)據(jù)怎么辦呢?JPA幫我們做了一個(gè)刷新的方法em.refresh(person); * 通過它我們就可以得到最新的數(shù)據(jù)了 */ em.refresh(person); System.out.println("----->>"+person.getName()); em.close(); factory.close(); }JPA中實(shí)現(xiàn)表間關(guān)聯(lián)關(guān)系 一的多
@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設(shè)置級(jí)聯(lián)刷新 ???? * CascadeType.PERSIST設(shè)置級(jí)聯(lián)保存 ???? * CascadeType.MERGE設(shè)置級(jí)聯(lián)更新 ???? * CascadeType.REMOVE設(shè)置級(jí)聯(lián)刪除 ???? * CascadeType.ALL設(shè)置四種級(jí)聯(lián) ???? * 這四種級(jí)聯(lián)都是對應(yīng)的四種方法才能起作用PERSIST(),MERGE(),REMOVE(),REFRESH() ???? * fetch=FetchType.LAZY支持LAzy加載,只有用到該屬性的時(shí)候才會(huì)讀集合數(shù)據(jù) ???? * 注意這時(shí)我們必須保持EntityManager是開著的,默認(rèn)是延遲加載 ???? * mappedBy="order"指定OrderItem類里面的order這個(gè)屬性來維護(hù)關(guān)系 ???? */ ????@OneToMany(cascade={CascadeType.ALL}, ????????????????????fetch=FetchType.LAZY, ????????????????????mappedBy="order") private Setitems = new HashSet (); // get set // }
為了我們添加Set集合方便我們通常的情況下我們的寫一個(gè)添加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")指明關(guān)聯(lián)關(guān)系的子段名 ???? * 即定義外鍵的名稱 ???? * ? ???? * */ ????@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
但是我們在數(shù)據(jù)庫中依然能看到orderIterm的數(shù)據(jù)
保存到數(shù)據(jù)庫里面了,這里就是設(shè)置級(jí)聯(lián)保存的緣故
CascadeType.PERSIST設(shè)置級(jí)聯(lián)保存
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")) ????????創(chuàng)建中間表來維護(hù)兩個(gè)表的關(guān)系 ???? * joinColumns=@JoinColumn(name="student_id")定義維護(hù)端在中間表中的關(guān)聯(lián)字段 ???? * inverseJoinColumns=@JoinColumn(name="teacher_id")定義被維護(hù)端在中間表中的關(guān)聯(lián)字段 ???? * ???? */ ????@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(); } /** * 建立學(xué)生跟老師的關(guān)系 */ @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(); } /** * 解除學(xué)生跟老師的關(guān)系 */ @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(); /** * 刪除老師的時(shí)候一定的解除掉老師和學(xué)生的關(guān)系 */ 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(); } /** *刪除學(xué)生 */ @Test public void deleteStudent() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); /** * 這個(gè)為什么不需要解除關(guān)系呢,主要是因?yàn)閷W(xué)生這一段是維護(hù)端 */ Student student = em.find(Student.class, 1); em.remove(student); em.getTransaction().commit(); em.close(); factory.close(); }聯(lián)合主鍵
我們多帶帶寫一個(gè)類作為主鍵,但是這個(gè)類的要滿足3條規(guī)則
它必須實(shí)現(xiàn)Serializable接口
它必須重寫字段的hashCode()和equals()方法
要在類上表明@Embeddable,這個(gè)注解的意思就是讓它的屬性在AirLine也正常做屬性
那么我們在主體類里面用這個(gè)主鍵類做為id,在id上面加上@EmbeddedId表明就是用主鍵類的屬性作為主鍵,并映射到數(shù)據(jù)庫表中
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; // 注意這里一定的時(shí)間他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 配置
使用步驟類似上面介紹,關(guān)鍵是要理解一對一、一對多、多對一、多對多的關(guān)聯(lián)關(guān)系
引入jpa yml文件org.springframework.boot spring-boot-starter-data-jpa
# maven打包 clean compile package spring: # 熱重啟 devtools: restart: enabled: true # 數(shù)據(jù)源 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實(shí)體類映射數(shù)據(jù)表
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;個(gè)別使用方法可以瀏覽其他教程介紹加強(qiáng)一下
Spring For All 社區(qū) Spring Data JPA 從入門到進(jìn)階系列教程
SpringBoot實(shí)戰(zhàn)SpringDataJPA
使用 Spring Data JPA 簡化 JPA 開發(fā)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/71560.html
摘要:一從零搭建環(huán)境本次我使用的是編輯器來搭建和環(huán)境首先,我們在新建項(xiàng)目的時(shí)候,選擇,然后就行了。可以看出,本次的版本為。這是一個(gè)非常好用的插件,有了它我們可以不用寫繁瑣的方法。非常適合我們做一些簡答的測試和小功能。 前言 只有光頭才能變強(qiáng)。 文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家對SpringB...
閱讀 829·2023-04-26 00:37
閱讀 715·2021-11-24 09:39
閱讀 2141·2021-11-23 09:51
閱讀 3801·2021-11-22 15:24
閱讀 741·2021-10-19 11:46
閱讀 1873·2019-08-30 13:53
閱讀 2421·2019-08-29 17:28
閱讀 1324·2019-08-29 14:11