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=?
相关文章
相关标签/搜索