這個 問題困擾我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=?