JPA 實戰 OneToOne

由於公司的項目是基本JPA作的數據處理,想總結實際項目中一些基本的用法。 java

1.由於項目基於maven,因此在resources目錄下須存放JPA基本的配置文件META-INF/persistence.xml,測試時通常使用derby,爲了更清楚的瞭解JPA執行的動做,show_sql,format_sql,hbm2ddl.auto三個屬性都須要設置。hbm2ddl.auto 不要設置成create-drop ,由於測試經過後,咱們能夠直接打開數據表,觀察 java bean 在 數據庫中對應的表結構。 sql

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="NewPersistenceUnit">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>org.pan.domain.Account</class>
        <class>org.pan.domain.AccountHeaderImage</class>
        <properties>
            <property name="hibernate.connection.url" value="jdbc:derby:test;create=true"/>
            <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>
            <property name="hibernate.connection.username" value=""/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
        </properties>
    </persistence-unit>
</persistence>

2. 實體類:一個帳戶(Account)會擁有一個頭像(AccountHeaderImage),他們是一對一對關係。一般咱們會創建一個雙向的一對一來表現這樣方式,即在雙邊都添加@oneToOne 註解,但有一點必定要清楚,無論是加載任何一方的數據,另外一方都會被加載出來,致使列表的查詢變爲1+n的查詢。(有一個比較牽強的理由:由於帳戶與頭像自己是一個整理,只是在數據上進行分開存儲,但在面向對象的層面他們仍是總體)。 數據庫

因此在項目中我會盡可能的減小@oneToOne的雙向關聯,而改爲單向。即帳戶包含圖片,頭像作爲帳戶的外鍵。具體的標註以下: apache


@Entity
public class Account extends AbstractDomain {

    @Column
    private String username;
    @Column
    private String password;
    @OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    private AccountHeaderImage accountHeaderImage;

//getter and setter
}



@Entity
public class AccountHeaderImage extends AbstractDomain{
    @Lob
    private byte[] headerImage;
//getter and setter
}

若是 Account 中fetchType使用Lazy 的話,則默認加載Account時不會加載AccountHeaderImage,需調用getAccountHeaderImage()纔會加載。以下以id的方式加載Account時,產生的sql語句以下: dom


select account0_.id as id1_0_0_, account0_.accountHeaderImage_id as accountH4_0_0_,
account0_.password as password2_0_0_,account0_.username as username3_0_0_ 
from Account account0_ where account0_.id=?
若是調用account.getAccountHeaderImage().getId(),則會多出一條sql,代表只有在須要用時才作加載:


select accounthea0_.id as id1_1_0_,accounthea0_.headerImage as headerIm2_1_0_ from AccountHeaderImage accounthea0_ where         accounthea0_.id=?
但咱們通常作加載時這樣作:


Hibernate.initialize(account.getAccountHeaderImage());
若是咱們在Account 中 fetchType 使用EAGER的話,則經過id加載Account 會產生以下sql :


select
        account0_.id as id1_0_0_,
        account0_.accountHeaderImage_id as accountH4_0_0_,
        account0_.password as password2_0_0_,
        account0_.username as username3_0_0_,
        accounthea1_.id as id1_1_1_,
        accounthea1_.headerImage as headerIm2_1_1_ 
    from
        Account account0_ 
    left outer join
        AccountHeaderImage accounthea1_ 
            on account0_.accountHeaderImage_id=accounthea1_.id 
    where
        account0_.id=?
相關文章
相關標籤/搜索