顯示具有 Hibernate 標籤的文章。 顯示所有文章
顯示具有 Hibernate 標籤的文章。 顯示所有文章

2016年12月19日 星期一

Hibernate Criteria - DQL

Hibernate - Criteria

參考:
http://openhome.cc/Gossip/HibernateGossip/CriteriaBasic.html

範例:
1.add()
- org.hibernate.criterion.Criteria 實例代表著一個條件,您要使用org.hibernate.Criteria的add()方法加入這些條件實例,例如查詢” age”大於20且小於40的資料

- 使用add()時,預設是使用and來組合條件

- gt()大於 lt小於
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.gt("age", new Integer(20)));
criteria.add(Restrictions.lt("age", new Integer(40)));
List users = criteria.list();

2.or()
- age等於(eq)20或(or)age為空(isNull)的條件
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.or(
               Restrictions.eq("age", new Integer(20)),
               Restrictions.isNull("age")
           ));
List users = criteria.list();

3.like()
- 查詢"name"中名稱為"just"開頭的資料:
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.like("name", "just%"));
List users = criteria.list();

4.in()
- 條件要放 『陣列 [] 』
String[] queryArray = {"John", "Ian"}

criteria.add(Restrictions.in(columnName, queryArray)); // 使用criteria columnName要放『物件的名稱』not 欄位名稱

5.between()
- 要注意型態問題(ex. timestamp)
Criteria criteria = session.createCriteria(AuditTrail.class);
criteria.add(Restrictions.between("auditDate", sDate, eDate));

6.Restrictions的幾個常用限定查詢方法如下表所示:
方 法說 明
Restrictions.eq等於
Restrictions.allEq使用Map,使用key/value進行多個等於的比對
Restrictions.gt大於 >
Restrictions.ge大於等於 >=
Restrictions.lt小於 <
Restrictions.le小於等於 <=
Restrictions.between對應SQL的BETWEEN子句
Restrictions.like對應SQL的LIKE子句
Restrictions.in對應SQL的in子句
Restrictions.andand關係
Restrictions.oror關係
Restrictions.sqlRestrictionSQL限定查詢

2016年12月16日 星期五

Hibernate SQL - DML、DQL、JOIN 範例

SQL
參考:http://blog.csdn.net/vacblog/article/details/7769976

-Select
1.addEntity()
透過『addEntity()』將"table"與"實體類"關聯在一起
這樣可以融合SQL簡潔的語法與Hibernate的方便性

使用addEntity()的大前提
-查詢返回的是某個table的全部數據  
-該table有對應的映射實體

這時候才能透過addEntity()方法將查詢結果轉換成實體
Query query = session.createSQLQuery(
"SELECT * FROM user_account ua WHERE ua.account=:account AND ua.user_email=:emailAddress ")
.addEntity(UserAccountEntity.class) //結合entity的方式把資料傳回來,但使用時有前提
.setParameter("account", account)
.setParameter("emailAddress", emailAddress);
resultList = query.list();

2.使用別名的addEntity()
String sql = "select {myUser.*} from user_information myUser ORDER BY myUser.id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity("myUser", UserInformationEntity.class);

3.addScalar()
最基本的SQL查询就是取得一個物件的列表:
session.createSQLQuery("select * from person_inf").list();  
session.createSQLQuery("select id,name,age from person_inf").list();  

此時會返回一個Object陣列组成的List,陣列每個元素都是person_inf表的一個欄位值。Hibernate會使用ResultSetMetadata來判定返回的值的實際順序跟類型。
但是在JDBC中過多的使用ResultSetMetadata會降低程序的性能。為避免過多使用ResultSetMetadata或者指定更加明確的返回值類型,我們可以使用addScalar()方法提高效能:
session.createSQLQuery("select * from person_inf")  
.addScalar("name",StandardBasicTypes.STRING)  
.addScalar("age",StandardBasicTypes.INT)  
.list();  

上述查询指定了:
-SQL查询欄位。
-要返回的欄位值和類型。
但是他仍然會返回Object陣列,但是此時不再使用ResultSetMetdata,而是明確的將\name和age按照String和int類型從resultset中取出。同時,也指明了就算query是使用*来查询的,可能獲得超過列出的這3個欄位,也僅僅會返回這3個欄位的值。

4. Join tables & 只傳回特定欄位值
Query query = session.createSQLQuery(
   "SELECT ua.f_service FROM user_account ua INNER JOIN service_account sa ON ua.f_service=sa.id
    WHERE sa.account=:serviceAccount AND ua.account=:account AND ua.user_email=:emailAddress ")
   
   .addScalar("f_service",StandardBasicTypes.INTEGER) 
   
   .setParameter("serviceAccount", serviceAccount)
   .setParameter("account", account)
   .setParameter("emailAddress", emailAddress);

resultList = query.list();

//get serviceId (createSQLQuery return Object[], but we only select f_service so only return an Object)

if (resultList.size() > 0) {
    Object aResult = resultList.get(0); //因為只有一個欄位值,所以傳回的並不是陣列,只是一個object
    serviceId = Integer.valueOf(String.valueOf(aResult));
}
下列語法也通用
Query query = session.createSQLQuery(
   "SELECT ua.f_service FROM user_account ua, service_account sa 
    WHERE ua.f_service=sa.id and sa.account=:serviceAccount AND ua.account=:account AND ua.user_email=:emailAddress ")
要是有『多個查詢值 select a,b,c......』會返回object[],使用下列方法接取
Object[] aResult = (Object[]) resultList.get(0);

5.透過addEntity、addScalar做join
http://blog.maxkit.com.tw/2014/03/hibernate-addentity-addscalar.html

2016年12月15日 星期四

Hibernate HQL - DML、DQL、JOIN 範例

HQL
-Select 
1.利用 ? 設定 sql 中的參數,搭配 query.setParameter("第幾個問號",變數);
Session session = BackendHibernateUtil.getSession();
List resultList = new LinkedList<>();
try {
     Query query = session.createQuery("FROM CtrlSourceAreaEntity WHERE source_type = ?");
     query.setParameter(0,sourceType);
     resultList = query.list();
} catch (HibernateException e) {
     log.error("XMLParserDAO @querySourceAreaId Fail:", e);
} finally {
     session.close();
}
return resultList;
2.利用 :Name 設定參數
"FROM CtrlSourceAreaEntity WHERE source_type = :sourceType"
 query.setParameter("sourceType",sourceType);

3.SQL Query In 設定參數
Query query = session.createQuery("FROM ScheduleDownloadEntity WHERE status in (:statusNames)  ORDER BY create_time ");
query.setParameterList("statusNames", statusList);
resultList = query.list();

-Update
1.executeUpdate()是執行DML的意思
 Query query = session.createQuery("UPDATE UserAccountEntity SET password = ? where f_service = ? AND account = ? AND user_email = ?");
 query.setParameter(0, userPasswordMD5);
 query.setParameter(1, serviceId);
 query.setParameter(2, account);
 query.setParameter(3, emailAddress);
 query.executeUpdate(); //這句是commit的意思

-Delete
1.executeUpdate() 是執行DML的意思

2.executeUpdate() 會傳回 int 影響的資料筆數
Query query = session.createQuery("DELETE EdititemEntity WHERE kind = ? AND post_time BETWEEN  ? AND ? ");
query.setParameter(0, taskNumber);
query.setParameter(1, startDate);
query.setParameter(2, endDate);
int resultCount = query.executeUpdate(); //可以取得DML影響的資料筆數

-Insert
1.將傳進來的 entity 實體 透過 session.save() 的方式把資料存進DB
public void insertData(EdititemEntity edititemEntity) {
Session session = Opv_lyHibernateUtil.getSession(); //Hibernate Session Connect
Transaction tx = session.beginTransaction(); //一組交易
try {
     session.save(edititemEntity); //將傳進來的Entity存進DB(透過Hibernate專屬方法)
     tx.commit(); //交易確認
} catch (HibernateException e) {
     tx.rollback(); //交易取消
     log.error("CategoryDAO @insertData Fail,newsId={},error={}", edititemEntity.getId(), e);
} finally {
     session.close();
}
}

HQL-Join

參考:
http://openhome.cc/Gossip/HibernateGossip/ManyToOne.html

多對一:
一個簡單的實體與實體間之關係為『多對一』的關係,例如『使用者』與『房間』的關係就是多對一的關係,多個使用者使用同一房間。

範例目標:

A:每個 user 有特定的 serviceId(f_service) ,多個user會對上同一個serviceId,希望透過HQL的方式,取得user時,順便取得service_account




1.實體設定(UserAccountEntity)

-在多對一的情況下,『多』的實體才需要特別設定,『一』的部份不用調整,因此我們只調整UserAccount
-UserAccountEntity.class
UserAccountEntity類別中有一serviceAccountEntity屬性,將參考至serviceAccountEntity實例,多個User實例可共同參考一個service實例











2.設定檔(UserAccountEntity.hbm.xml)
- class="絕對路徑""
- column="f_service" → userAccount的f_service(FK)會去參考到serviceAccount的id(PK),兩張table才會連結在一起
- cascade表示主控方(User)進行save-pdate、delete等 相關操作時,被控 方(Room)是否也一併進行相關操作,簡單的說,也就是您儲存或更新User實例時,被參考到的Room實例是否一併對資料庫發生儲存或操作,設定為 all,表示主控方任何操作,被控方也進行對應操作。

-把原先的fService先註解掉



-設定mana-to-one的參數















3.查詢結果
- 重要:INNER JOIN 是 userAccount實體中的serviceAccount屬性




- 結果
每個傳回的結果都帶有UserAccountEntity & ServiceAccountEntity

2016年9月10日 星期六

How To Generate Hibernate Entity With Intellj

說明
- 利用Intellj 連接SQLServer DataBase ,並自動產生Hibernate Entity
- Hibernate 設定檔設置

環境
- Intellj 13
- SQLServer 2012

1.Intellj 連接資料庫

a.建立連線
- 點擊最右側Database長條圖示
- 點擊 + 號新增Database資源連線
- 選擇Driver (此範例使用jTds)
SQL Server有2種不同Driver,以下範例使用jTds(不同Driver後面的設定會有些許不同)















b.帳密設定
- Database:"輸入資料庫名稱"
- User:"輸入帳號"
- Password:"輸入密碼"
- 按下 Test Connection 測試連線,若成功連線,會有下列的圖示的跳出視窗
















c.確認Table
選擇scheme & Table
- 檢查是否與該資料庫內容一樣













d.替 Intellj 加入 Hibernate Mapping功能
- 成功開啟後,最左邊的欄位,會出現Persistence的長條功能鍵














e.Mapping  Hibernate 與 Database(建立兩者關係)
- 點擊Persistence長條
- 選擇poc(此專案叫poc)並點擊右鍵
- Genetate Persistence Mapping → By DatabaseScheme






















2.Generate Hibernate Entity
- Choose Data Source:選擇上面設定的連線資源
- Package:選擇產出後,要放至哪個路徑
- 需要一些時間來跑
- 找到目標Table (範例Table為:user_information),並點擊勾選

設定檔相關勾選:
1. Add to Scheme Factory:將該xml連線加入指定的xxxx.cfg.xml

2. Generate Column Properties:是某將DB欄位的相關屬性
(流水號identity、資料長度、not null...顯示在hbm.xml上面)


3.Generate SeparateXML per Entity:是否要產生XML檔(本範例不勾選)


若沒有出現任何Table:對著空白處按下『右鍵』,RefreshTable

















3.成功產出畫面














4.額外補充 - SQLServer Driver設定不同處

- 在xxxx.hcfg.xml設定檔中

a.Microsoft







b.jTds





c.Mapping至對映的entity檔案(有無產xml檔,會有不同寫法)

2016年7月22日 星期五

建置第一個Hibernate In Intellj

環境配置:

  • Intellj 1.4
  • JDBC4
  • Hibernate jar (少其中一個可能都會出錯)




















內容參考至:




Step1.檔案結構目錄
Step2.設置hibernate.cfg.xml
<hibernate-configuration>
    <session-factory>
        <!-- 顯示實際操作資料庫時的SQL -->
        <property name="show_sql">true</property>
        <!-- 將顯示的SQL排版,方便觀看 -->
        <property name="format_sql">true</property>
        <!-- SQL方言,這邊設定的是SQLServer -->
        <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
        <!-- JDBC驅動程式 -->
        <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <!-- JDBC URL -->
        <property name="connection.url">jdbc:sqlserver://127.0.0.1:1433;DatabaseName=testdb</property>
        <!-- 資料庫使用者 -->
        <property name="connection.username">sa</property>
        <!-- 資料庫密碼 -->
        <property name="connection.password">578989</property>
        <!-- 物件與資料庫表格映射文件 -->
        <mapping resource="User.hbm.xml">
    </mapping></session-factory>
</hibernate-configuration>



Step3.設置User.hbm.xml
-重點注意事項
1.資料庫每個欄位都要記得設定到<property>
2.其中id是個特殊的屬性,Hibernate會使用它來作為主鍵識別,您可以定義主鍵產生的方式,這是在XML映射文件中完成
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
        PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <!--<class>標籤的name屬性為所映射的物件,而table為所映射的表格;-->
    <class name="Hibernate.UserInformationEntity" table="user_information">
        <id name="id" column="id"> <!--<id>中 column屬性指定了表格欄位,而 type屬性指定了User實例的中的id之型態。-->
            <generator class="native"/> <!--<id>中主鍵的產生方式在這邊設定為"native",表示主鍵的生成方式由Hibernate根據資料庫Dialect 的定義來決定-->
            <!--<generator class="identity"/>-->
            <!--identity-->
        </id>
        <!--<property>標籤中的column與type都各自指明了表格中欄位與物件中屬性的對應。-->
        <property name="account" column="account"/>
        <property name="name" column="name"/>
        <property name="age" column="age"/>
        <property name="create_time" column="create_time"/>
    </class>
</hibernate-mapping>


Step4.建立實體,與表格對應
-重點注意事項
1.資料庫欄位『型態是甚麼』,實體就要設一樣,否則會出錯
ex.資料庫:age int not null  實體:int age;
public class UserInformationEntity {
    int id =0;
    String account;
    String name;
    int age = 0;
    Date create_time;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Date getCreate_time() {
        return create_time;
    }
    public void setCreate_time(Date create_time) {
        this.create_time = create_time;
    }
}
Sept5.設定SessionFactory實例,連線用 
-重點注意事項  
1.也可直接寫在main class之中,一個應用程式當中通常只需要一個SessionFactory實例, 為了方便整個應用取得同一個SessionFactory實例, 可以撰寫一個HibernateUtil類別 
2.要如何寫在main class可參考: http://blog.csdn.net/zs234/article/details/9108533
package Hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
 * Created by ytchen on 2016/7/22.
 */
public class HibernateUtil {
    private static SessionFactory sessionFactory;
    static {
        try {
            sessionFactory = new Configuration().configure()
                    .buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    public static void shutdown() {
        getSessionFactory().close();
    }
Sept6.馬上來試用Hibernate吧 
package Hibernate;

import org.hibernate.Transaction;

import org.hibernate.Session;



import java.util.Date;



/**

 * Created by ytchen on 2016/7/22.

 */

public class HibernateDemo {

    public static void main(String[] args) {

        UserInformationEntity user = new UserInformationEntity();

        user.setAccount("Ian");

        user.setName("Ian");

        user.setAge(20);

        user.setCreate_time(new Date());



        // 開啟Session,相當於開啟JDBC的Connection

        Session session = HibernateUtil.getSessionFactory().openSession();

        // Transaction表示一組會話操作

        Transaction tx= session.beginTransaction();

        // 將物件映射至資料庫表格中儲存

        session.save(user);

        tx.commit();

        session.close();



        System.out.println("新增資料OK!請用Sqlserver觀看結果!");



        HibernateUtil.shutdown();

    }

}

2016年7月21日 星期四

Hibernate 心得

1.Hibernate簡介:

Hibernate 是「物件/關係對應」(Object/Relational Mapping)的解決方案,簡寫為ORM,簡單的說就是將 Java 中的物件與物件關係,映射至關聯式資料庫中的表格與表格之間的關係, Hibernate 提供了這個過程中自動對應轉換的方案。

白話:
直接將Java設計好的物件(存放欄位跟資料的物件),直接跟資料庫中的表格做連結,省下中間很多的設定


2.甚麼是物件:

  • 我們自己建的一個Class,用來存放資料庫欄位跟資料,之後可以new這個物件出來做事情
  • 利用Get & Set 做出存取的方法


public class EipMemberBean {
    String m_account = "";
    String m_password = "";
    String m_block = "";
    String m_name ="";
    String m_email ="";
    String m_gender ="";
    String m_create_date ="";
    String m_create_time ="";
    String ls_ad ="";

    public String getM_password() {
        return m_password;
    }

    public void setM_password(String m_password) {
        this.m_password = m_password;
    }

    public String getM_account() {
        return m_account;
    }

    public void setM_account(String m_account) {
        this.m_account = m_account;
    }

    public String getM_block() {
        return m_block;
    }

    public void setM_block(String m_block) {
        this.m_block = m_block;
    }

    public String getM_name() {
        return m_name;


    }