程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Hibernate單向一對多應注意的問題

Hibernate單向一對多應注意的問題

編輯:關於JAVA

這個 問題困擾我10多天,終於干掉了。

本人使用myeclipse6.5ga,進行hibernate一對多單向關聯實例。

一直報如下異常:

Hibernate:
  insert
  into
    hbql.score
    (score, type)
  values
。。。。。。。。。。。。。。。。。。。
17:03:32,484 DEBUG JDBCExceptionReporter:69 - could not insert: [score.Score] [insert into hbql.score (score, type) values (?, ?)]
java.sql.SQLException: Field 'sid' doesn't have a default value
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
..................//太長發不了。省略點
17:03:32,484 WARN JDBCExceptionReporter:77 - SQL Error: 1364, SQLState: HY000
17:03:32,484 ERROR JDBCExceptionReporter:78 - Field 'sid' doesn't have a default value
保存對象student.Student失敗!
17:03:32,484 DEBUG JDBCTransaction:152 - rollback
org.hibernate.exception.GenericJDBCException: could not insert: [score.Score]
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
    ...........................//太長發不了。省略點
Caused by: java.sql.SQLException: Field 'sid' doesn't have a default value
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)

測試程序如下:

Student student=new Student("huizhi","2708",200);
Score score1=new Score(98,"1");
Score score2=new Score(90,"2");
Set set=new HashSet();
set.add(score1);
set.add(score2);
student.setScores(set);
saveObject(student);
printStudents();
----------------------------------------------------------------------------------------------------------------------

映射文件Student.hbm.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="student.Student" table="student" catalog="hbql" >
     <id name="id" type="java.lang.Integer">
       <column name="id" />
       <generator class="native" />
     </id>
<set name="scores" table="score" cascade="save-update" inverse="false">
   <key>
     <column name="sid" not-null="true" />
   </key>
   <one-to-many class="score.Score" />
</set>
     <property name="name" type="java.lang.String">
       <column name="name" length="20" not-null="true" />
     </property>
     <property name="number" type="java.lang.String">
       <column name="number" length="20" not-null="true" />
     </property>
     <property name="classid" type="java.lang.Integer">
       <column name="classid" not-null="true" />
     </property>
   </class>
</hibernate-mapping>
----------------------------------------------------------------------------------------------------------------

映射文件Score.hbm.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="score.Score" table="score" catalog="hbql">
     <id name="id" type="java.lang.Integer">
       <column name="id" />
       <generator class="native" />
     </id>
     <property name="score" type="java.lang.Integer">
       <column name="score" not-null="true" />
     </property>
     <property name="type" type="java.lang.String">
       <column name="type" length="20" not-null="true" />
     </property>
   </class>
</hibernate-mapping>
---------------------------------------------------------------------------------------------------------------------

持久化類

public class Score implements java.io.Serializable {
     private Integer id;
     private Integer score;
     private String type;
     …..
public class Student implements java.io.Serializable {
     private Integer id;
     private String name;
     private String number;
     private Integer classid;
     private Set scores=new HashSet();
     ….
---------------------------------------------------------------------------------------------------------------------

數據庫表MySQL

DROP TABLE IF EXISTS `hbql`.`student`;
CREATE TABLE `hbql`.`student` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(20) NOT NULL,
  `number` varchar(20) NOT NULL,
  `classid` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `hbql`.`score`;
CREATE TABLE `hbql`.`score` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `score` int(10) unsigned NOT NULL,
  `type` varchar(20) NOT NULL,
  `sid` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_score_1` (`sid`),
  CONSTRAINT `FK_score_1` FOREIGN KEY (`sid`) REFERENCES `student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

能解決此問題主要得益於該BLOG:http://suhaoyuan.spaces.live.com/Blog/cns!2659D3AC8253C554!217.entry上的如下一段話。

留意<set>元素中的inverse屬性,該屬性表示關聯關系由主控(一方)還是受控方(多方)維護。所謂關聯關系的維護就是受控方的外鍵插入由誰來控制。inverse默認為false,表示由主控方來控制。當主控方控制時,插入SQL的語句會分兩條進行

insert into Items(itemName, itemPrice, orderId) values('aa', '5.95', NULL);

update Items set orderId = 3 where itemName = 'aa' and itemPrice = '5.95';

因為主控方控制關聯關系,意味受控方在插入數據時,不會考慮其外鍵引用,直接插入為NULL,直到主控方執行更新操作。

因為HIbernate分兩條SQL語句插入Score對象。所以在SCORE表中,第一次外鍵為空。所以定義數據庫中外鍵時默認值應為NULL. 第二次是更新該條記錄的外鍵。本人在創建SCORE表外鍵SID默認是不能為空。所以會出現此種情況,更改為NULL一切正常。

如下為HIbernate生成的SQL語句:

部分。

Hibernate:
  insert
  into
    hbql.score
    (score, type)
  values
    (?, ?)
Hibernate:
  update
    hbql.score
  set
    sid=?
  where
    id=?

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