hibernate不支持insert into values()

DML(數據操作語言)風格的操作(DML-style operations)

hence manipulating (using the SQL Data Manipulation Language (DML) statements: INSERT, UPDATE, DELETE) data directly in the database will not affect in-memory state. However, Hibernate provides methods for bulk SQL-style DML statement execution which are performed through the Hibernate Query Language (第 14 章 HQL: Hibernate查詢語言). 就像已經討論的那樣,自動和透明的 對象/關係 映射(object/relational mapping)關注於管理對象的狀態。 這就意味着對象的狀態存在於內存,因此直接操作 (使用 SQL Data Manipulation Language(DML,數據操作語言)語句 :INSERT ,UPDATEDELETE) 數據庫中的數據將不會影響內存中的對象狀態和對象數據。 不過,Hibernate提供通過Hibernate查詢語言(第 14 章 HQL: Hibernate查詢語言)來執行大批 量SQL風格的DML語句的方法。

UPDATEDELETE語句的語法爲: ( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)? 有幾點說明:

  • 在FROM子句(from-clause)中,FROM關鍵字是可選的

  • 在FROM子句(from-clause)中只能有一個實體名,它可以是別名。如果實體名是別名,那麼任何被引用的屬性都必須加上此別名的前綴;如果不是別名,那麼任何有前綴的屬性引用都是非法的。

  • 不能在大批量HQL語句中使用第 14.4 節 “join 語法的形式”(顯式或者隱式的都不行)。不過在WHERE子句中可以使用子查詢。可以在where子句中使用子查詢,子查詢本身可以包含join。

  • 整個WHERE子句是可選的。

舉個例子,使用Query.executeUpdate()方法執行一個HQL UPDATE語句(: (方法命名是來源於JDBC's PreparedStatement.executeUpdate()):

Session session = sessionFactory.openSession();
  Transaction tx = session.beginTransaction();

  String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
  // or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
  int updatedEntities = s.createQuery( hqlUpdate )
          .setString( "newName", newName )
          .setString( "oldName", oldName )
          .executeUpdate();
  tx.commit();
  session.close();

HQL UPDATE語句,默認不會影響更新實體的第 5.1.7 節 “版本(version)(可選)”或者第 5.1.8 節 “timestamp (可選)”屬性值。這和EJB3規範是一致的。但是,通過使用versioned update,你可以強制Hibernate正確的重置version或者timestamp屬性值。這通過在UPDATE關鍵字後面增加VERSIONED關鍵字來實現的。

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
        .setString( "newName", newName )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

注意,自定義的版本類型(org.hibernate.usertype.UserVersionType)不允許和update versioned語句聯用。

執行一個HQL DELETE,同樣使用 Query.executeUpdate() 方法:

Session session = sessionFactory.openSession();
  Transaction tx = session.beginTransaction();

  String hqlDelete = "delete Customer c where c.name = :oldName";
  // or String hqlDelete = "delete Customer where name = :oldName";
  int deletedEntities = s.createQuery( hqlDelete )
          .setString( "oldName", oldName )
          .executeUpdate();
  tx.commit();
  session.close();

Query.executeUpdate()方法返回的整型值表明了受此操作影響的記錄數量。 注意這個數值可能與數據庫中被(最後一條SQL語句)影響了的“行”數有關,也可能沒有。一個大批量HQL操作可能導致多條實際的SQL語句被執行, 舉個例子,對joined-subclass映射方式的類進行的此類操作。這個返回值代表了實際被語句影響了的記錄數量。在那個joined-subclass的例子中, 對一個子類的刪除實際上可能不僅僅會刪除子類映射到的表而且會影響“根”表,還有可能影響與之有繼承關係的joined-subclass映射方式的子類的表。

INSERT語句的僞碼是: INSERT INTO EntityName properties_list select_statement. 要注意的是:

  • 只支持INSERT INTO ... SELECT ...形式,不支持INSERT INTO ... VALUES ...形式.

    properties_list和SQL INSERT語句中的字段定義(column speficiation)類似。對參與繼承樹映射的實體而言,只有直接定義在給定的類級別的屬性才能直接在properties_list中使用。超類的屬性不被支持;子類的屬性無意義。換句話說,INSERT天生不支持多態。

  • select_statement可以是任何合法的HQL選擇查詢,不過要保證返回類型必須和要插入的類型完全匹配。目前,這一檢查是在查詢編譯的時候進行的,而不是把它交給數據庫。注意,在HibernateType間如果只是等價(equivalent)而非相等(equal),會導致問題。定義爲org.hibernate.type.DateTypeorg.hibernate.type.TimestampType的兩個屬性可能會產生類型不匹配錯誤,雖然數據庫級可能不加區分或者可以處理這種轉換。

  • 對id屬性來說,insert語句給你兩個選擇。你可以明確地在properties_list表中指定id屬性(這樣它的值是從對應的select表達式中獲得),或者在properties_list中省略它(此時使用生成指)。後一種選擇只有當使用在數據庫中生成值的id產生器時才能使用;如果是“內存”中計算的類型生成器,在解析時會拋出一個異常。注意,爲了說明這一問題,數據庫產生值的生成器是org.hibernate.id.SequenceGenerator(和它的子類),以及任何org.hibernate.id.PostInsertIdentifierGenerator接口的實現。這兒最值得注意的意外是org.hibernate.id.TableHiLoGenerator,它不能在此使用,因爲它沒有得到其值的途徑。

  • 對映射爲versiontimestamp的屬性來說,insert語句也給你兩個選擇,你可以在properties_list表中指定(此時其值從對應的select表達式中獲得),或者在properties_list中省略它(此時,使用在org.hibernate.type.VersionType 中定義的seed value(種子值))。

執行HQL INSERT語句的例子如下:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
        .executeUpdate();
tx.commit();
session.close();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章