程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Spring入門---JPA學習筆記,---jpa學習筆記

Spring入門---JPA學習筆記,---jpa學習筆記

編輯:JAVA綜合教程

Spring入門---JPA學習筆記,---jpa學習筆記


  用了一段時間的Spring,到現在也只是處於會用的狀態,對於深入一點的東西都不太了解。所以決定開始深入學習Spring。

  本文主要記錄JPA學習。在學習JPA之前,需要了解一些ORM的概念。

ORM概念:

  對象關系映射ORM(Object/Relation Mapping)是一種為了解決面向對象和關系數據之間存在互不匹配現象的技術(范式不匹配)。簡而言之,ORM是通過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到數據庫中。本質上是將數據從一種形式轉換到另外一種形式。(個人考慮:但是這麼做,感覺好像和一般方法比起來會有額外的開銷吧?待解決)

  范式不匹配:

 

ORM具備功能:

  一般ORM框架包括以下四個功能:

 

映射發生情況:

  對象-關系映射一般發生在以下情況:

 

 


  以上就是JPA的一些概念,接下來上JPA。

JPA功能:

  JPA(Java persistence API)主要用用於Java中處理持久化操作。對ORM特性和功能進行標准化。分別定義了用來將對象模型映射到關系模型的API、可以在對象上執行CRUD操作、一種對象查詢語言以及通過對象圖獲取數據的標准API。

  JPA好處:???都還沒怎麼用,沒法做出比較。還是先使用一段時間後,再來評價

 

使用JPA:

定義實體:

  實體定義:一個對象在數據庫端與一個帶有主鍵的記錄相對應,那麼該對象就稱為實體。

  下面代碼定義了一個最簡單的實體類:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * 
 * <p>ClassName: User.java<p>
 * <p>用戶實體類<p>
 * @author linzj
 * @createTime 2016年3月17日  下午1:08:35
 */
@Entity
@Table(name="user")
public class User {
    
    @Id
    @GeneratedValue
    private Long id;
    
}

  JPA為映射提供了java注解,可以發現這些注解都在javax.persistence包下。上面的@Entity注解定義了User類為持久化類型,並有一個對應的表。@Table注解指定了表名,如果沒有指定表明則默認使用類名為其表名。

  @Id注解標記了主鍵屬性。如果主鍵列名與屬性名不匹配,則可以使用@Column來指定對應的主鍵列名,如添加上@Column(name=”uid”),就與uid列表對應。應用程序並不負責生成主鍵值,而是在新記錄插入期間由JPA供應商分配(如Hibernate)。通過@GenerateValue注解告訴JPA,應用程序將不會負責分配主鍵值,而是有JPA供應商處理。

屬性映射到列:

  為了更加直觀的理解。我先建了一張User表:

mysql> create table user(
    -> id int(5) not null primary key auto_increment,
    -> username varchar(60) not null,
    -> passwd varchar(60) not null);
Query OK, 0 rows affected (0.14 sec)

mysql> describe user;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(5)      | NO   | PRI | NULL    | auto_increment |
| username | varchar(60) | NO   |     | NULL    |                |
| passwd   | varchar(60) | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+

  接下來我們就可以將剛剛的User實體類添加對應的屬性,並將屬性映射到上面這張user表中對應的列了:

/**
 * 
 * <p>ClassName: User.java<p>
 * <p>用戶實體類<p>
 * @author linzj
 * @createTime 2016年3月17日  下午1:08:35
 */
@Entity
@Table(name="user")
public class User {
    
    @Id
    @GeneratedValue
    private Long id;
    
    private String username;
    
    @Column(name = "passwd")
    private String password;
    
    @Transient
    private String others;
}

  因為表中沒有password這個字段,所以我們必須指定映射的列名,即指定password映射到passwd。我們還發現實體類中多了一個表裡沒有的屬性others,注意這個others屬性已經注解為@Transient,因此others屬性將被JPA忽略,不會進行映射。

對象之間創建關聯:

  數據庫關聯類型有:

  • 一對一(1:1)
  • 多對1(M:1)
  • 一對多(1:M)
  • 多對多(M:M)

一對一關聯:

/**
 * 
 * <p>ClassName: User.java<p>
 * <p>
 *     用戶實體類,通過@OneToOne注解標識一對一關聯,
 *     @JoinColumn注解更加User和Adress實體指定了
 *     表之間的外鍵關系。用戶表中的列引用了地址表
 * <p>
 * @author linzj
 * @createTime 2016年3月17日  下午1:08:35
 */
@Entity
@Table(name="user")
public class User {
    
    @Id
    @GeneratedValue
    private Long id;
    
    private String username;
    
    @Column(name = "passwd")
    private String password;
    
    @OneToOne
    @JoinColumn(name = "adress_id")//添加外鍵
    private Adress adress;
}


/**
 * 
 * <p>ClassName: Adress.java<p>
 * <p>地址實體類<p>
 * @author linzj
 * @createTime 2016年3月17日  下午1:52:30
 */
@Entity
public class Adress {
    //...pass
}

多對一:

/**
 * 
 * <p>ClassName: Employe.java<p>
 * <p>
 *     雇員實體類,使用了@ManyToOne注解,並使用了@JoinColumn指定兩表之間的外鍵關系,
 *     optional=false 標識關聯是Employe必須的,即:Employe不能單獨存在。
 * <p>
 * @author linzj
 * @createTime 2016年3月17日  下午1:55:11
 */
@Entity
public class Employe {
    
    //...pass
    
    @ManyToOne(optional = false)
    @JoinColumn(name = "company_id")
    private Company company;
    
}

@Entity
public class Company {
    //...pass
}

多對一:

/**
 * 
 * <p>ClassName: Student.java<p>
 * <p>
 *     學生實體類,@OneToMany注解在學生和書本之間創建了一對多的關系,
 *     用@JoinColumn指定外鍵,不同的是這次外鍵列存在於Book實體中。
 * <p>
 * @author linzj
 * @createTime 2016年3月17日  下午2:01:23
 */
@Entity
public class Student {
    
    //...pass
    @OneToMany
    @JoinColumn(name = "student_id")
    private Set<Book> books = new HashSet<Book>();
    
}

@Entity
public class Book {
    
    //...pass
    
}

多對多:

/**
 * 
 * <p>ClassName: Product.java<p>
 * <p>
 *     產品實體類,@ManyToMany創建多對多關聯,
 *     注意這裡用的是@JoinTable而不是@JoinColumn,
 *     因為一邊的多個實例可以與另一邊的多個實例相關聯。因此無法再一個列中保存指向另一個表的關聯數據。
 *     所以這裡就需要提供一個關聯表,該表包含每個表的主鍵列引用。
 *     本示例中,關聯表是product_catalog,joinColumns和inverseJoinColumns指定
 *     product_catalog表中的列名,joinColumns指定Product表主鍵的引用,inverseJoinColumns
 *     指定Catalog表主鍵的引用。
 * <p>
 * @author linzj
 * @createTime 2016年3月17日  下午2:07:47
 */
@Entity
public class Product {
    @Id
    @GeneratedValue
    private Long id;
    
    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "product_catalog", joinColumns = @JoinColumn(name = "product_id"), 
    inverseJoinColumns = @JoinColumn(name = "catalog_id"))
    private Set<Catalog> catalog = new HashSet<Catalog>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Set<Catalog> getCatalog() {
        return catalog;
    }

    public void setCatalog(Set<Catalog> catalog) {
        this.catalog = catalog;
    }
}

@Entity
public class Catalog {
    @Id
    @GeneratedValue
    private Long id;
}
/**
對應的表如下:
mysql> describe product_catalog;
+------------+------------+------+-----+---------+-------+
| Field      | Type       | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| product_id | bigint(20) | NO   | PRI | NULL    |       |
| catalog_id | bigint(20) | NO   | PRI | NULL    |       |
+------------+------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> select * from product_catalog;
+------------+------------+
| product_id | catalog_id |
+------------+------------+
|          1 |          1 |
|          1 |          2 |
+------------+------------+
2 rows in set (0.00 sec)

mysql> select * from product;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

mysql> select * from catalog;
+----+
| id |
+----+
|  1 |
|  2 |
+----+
*/

  關聯的方向性:

  關聯的方向性只有兩種:單向和雙向。

  在單向關聯中,只能從關聯的源對象到目標對象。雙向關聯則處理能從關聯的源對象到目標對象外,還可以從目標對象到源對象。

  在如下代碼中,我們只是將上面的Adress實體類修改了下,就構成了雙向關聯。我們在Adress實體類代碼中,添加了@OneToOne(mappedBy = "adress"),並且添加了mappedBy屬性,通過該屬性,JPA可以識別該屬性,從而管理兩個實體之間的關聯。使用mappedBy屬性的一邊可以看作成一個鏡子,或者是只讀的。它並不會對數據庫的數據產生影響。拿下面的代碼說明就是,用下面的實體類做持久化操作後,數據庫的Adress表裡並不會多一列關於user的字段。

@Entity
@Table(name="user")
public class User {
    
    @Id
    @GeneratedValue
    private Long id;
    
    private String username;
    
    @Column(name = "passwd")
    private String password;
    
    @OneToOne
    @JoinColumn(name = "adress_id")//添加外鍵
    private Adress adress;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Adress getAdress() {
        return adress;
    }

    public void setAdress(Adress adress) {
        this.adress = adress;
    }
    
}

@Entity
public class Adress {
    @Id
    @GeneratedValue
    private Long id;
    
    @OneToOne(mappedBy = "adress")
    private User user;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    
}

 

上面代碼放在我的GITHUB

另外提供一些關於JPA的博客:

http://www.cnblogs.com/holbrook/archive/2012/12/30/2839842.html

http://www.cnblogs.com/chenying99/p/3143516.html

以上是本人學習JPA的記錄,下一篇介紹配置和使用JPA。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved