1、在hibernate中,是先建类还是先建表? 从理论上讲是先建类后建表,但实际工作中,应该是先建表后建类。(原因是在没有hibernate之前,人们都是先建数据库表。) 2、如果在将类与表进行映射时,类名与表名不一致时。可以在类中指定表名。 //指明表的名称为_Teacher,与类名不一致 @Table(name=”_Teacher”) public class Teacher{
} 3、hibernate中的映射类型对照表。当然,在*.hbm.xml文件中可以不指定type属性的值,hibernate会自动为程序进行默认的转换。如果要手动指定,可以参照下表。
4、关联映射(最常用的是多对一(many to one)、一对一(one to one)。one to one是many to one的特例)。 在hibernate中,有两种方式进行映射,一种是annotation方式,另一种是*.hbm.xml方式。
many to one单向关联: ü 数据库表设计中需要在”many”的那方加一外键,并指向”one”方的主键。 ü 实体类中,需要在”many”的那个类中加上”one”方的类的一个变量属性。 ü .hbm.xml中,需要在”many”那个xml中加入 <many-to-one name="addressn1fk" column="addressId"/>。 说白了,”many”方,在数据库的角度来说,就是有外键的那个表所对应的实体类。同样适用于one to one。需抓住有外键的那个数据库。 *.hbm.xml方式: 一、模型介绍 多个人(Person)对应一个地址(Address)。 二、实体(省略getter、setter方法) Personn1fk.java: public class Personn1fk { private int personid; private String name; private int age; //引用one方的类型的变量 private Addressn1fk addressn1fk; … }
Addressn1fk.java: public class Addressn1fk { private int addressid; private String addressdetail; … }
三、表模型 mysql> desc address_n1kf; +---------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+--------------+------+-----+---------+----------------+ | addressid | int(11) | NO | PRI | NULL | auto_increment | | addressdetail | varchar(255) | YES | | NULL | | +---------------+--------------+------+-----+---------+----------------+
mysql> desc person_n1kf; +-----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+----------------+ | personid | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | age | int(11) | YES | | NULL | | | addressId | int(11) | YES | MUL | NULL | | +-----------+--------------+------+-----+---------+----------------+
四、生成的SQL脚本
CREATE TABLE `address_n1kf` ( `addressid` int(11) NOT NULL auto_increment, `addressdetail` varchar(255) default NULL, PRIMARY KEY (`addressid`) ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
DROP TABLE IF EXISTS `person_n1kf`;
CREATE TABLE `person_n1kf` ( `personid` int(11) NOT NULL auto_increment, `name` varchar(255) default NULL, `age` int(11) default NULL, `addressId` int(11) default NULL, PRIMARY KEY (`personid`), KEY `FK4571AF54A2A3EE48` (`addressId`), CONSTRAINT `FK4571AF54A2A3EE48` FOREIGN KEY (`addressId`) REFERENCES `address_n1kf` (`addressid`) ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
五、映射方法 Personn1fk.hbm.xml: <hibernate-mapping> <class name="com.lavasoft.dx._n_1_fk.Personn1fk" table="PERSON_n1fk"> <id name="personid"> <generator class="identity"/> </id> <property name="name"/> <property name="age"/> <!--用来映射关联PO column是Address在该表中的外键列名,name属性的值是Personn1fk 类中引用另一个类中的变量--> <many-to-one name="addressn1fk" column="addressId"/> </class> </hibernate-mapping>
Addressn1fk.hbm.xml: <hibernate-mapping> <class name="com.lavasoft.dx._n_1_fk.Addressn1fk" table="ADDRESS_n1fk"> <id name="addressid"> <generator class="identity"/> </id> <property name="addressdetail"/> </class> </hibernate-mapping>
hibernate.cfg.xml: 在该配置文件的<session-factory></session-factory>标签中加入 <mapping resource= com.lavasoft.dx._n_1_fk. Addressn1fk.hbm.xml> <mapping resource= com.lavasoft.dx._n_1_fk. Personn1fk.hbm.xml >
六、测试方法
public class Test_n1fk { public static void main(String[] args){ Personn1fk p1=new Personn1fk(); Personn1fk p2=new Personn1fk();
p1.setAge(21); p1.setName("p1");
p2.setAge(23); p2.setName("p2");
Addressn1fk add=new Addressn1fk(); add.setAddressdetail("郑州市经三路");
p1.setAddressn1fk(add); p2.setAddressn1fk(add);
Session session=HibernateUtil.getCurrentSession(); Transaction tx=session.beginTransaction(); session.save(add); session.save(p1); session.save(p2); tx.commit(); HibernateUtil.closeSession(); } }
七、测试结果
1) :正常保存. 推荐这么干!
session.save(p1); session.save(p2);
Hibernate: insert into ADDRESS_n1kf (addressdetail) values (?) Hibernate: insert into PERSON_n1kf (name, age, addressId) values (?, ?, ?) Hibernate: insert into PERSON_n1kf (name, age, addressId) values (?, ?, ?)
2) :正常保存. session.save(p1); session.save(p2); session.save(add);
Hibernate: insert into PERSON_n1kf (name, age, addressId) values (?, ?, ?) Hibernate: insert into PERSON_n1kf (name, age, addressId) values (?, ?, ?) Hibernate: insert into ADDRESS_n1kf (addressdetail) values (?) Hibernate: update PERSON_n1kf set name=?, age=?, addressId=? where personid=? Hibernate: update PERSON_n1kf set name=?, age=?, addressId=? where personid=?
3) :正常保存. session.save(add); // session.save(p1); // session.save(p2);
Hibernate: insert into ADDRESS_n1kf (addressdetail) values (?)
4) : 发生异常,不能保存. // session.save(add); session.save(p1); session.save(p2); Hibernate: insert into PERSON_n1kf (name, age, addressId) values (?, ?, ?) Hibernate: insert into PERSON_n1kf (name, age, addressId) values (?, ?, ?) Exception in thread "main" org.hibernate.TransientObjectException: com.lavasoft.dx._n_1_fk.Addressn1kf
one to one 单向关联:
事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似。只需要将原来的many-to-one元素增加unique="true"属性,用于表示N的一端也必须是唯一的,在N的一端增加了唯一的约束,即成为单向1-1。基于外键的单向1-1的配置将与无连接表N-1关联的many-to-one增加unique="true"属性即可。
一、模型介绍
一个人(Person)对应一个地址(Address)。
二、实体(省略getter、setter方法) Person11fk .java: public class Person11fk { private int personid; private String name; private int age; private Address11fk address11fk; … }
Address11fk.java: public class Address11fk { private int addressid; private String addressdetail; … }
三、表模型
mysql> desc address_11fk; +---------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra| +---------------+--------------+------+-----+---------+----------------+ | addressid | int(11)| NO | PRI | NULL| auto_increment | | addressdetail | varchar(255) | YES| | NULL|| +---------------+--------------+------+-----+---------+----------------+
mysql> desc person_11fk; +-----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra| +-----------+--------------+------+-----+---------+----------------+ | personid| int(11)| NO | PRI | NULL| auto_increment | | name| varchar(255) | YES| | NULL|| | age | int(11)| YES| | NULL|| | addressId | int(11)| YES| UNI | NULL|| +-----------+--------------+------+-----+---------+----------------+
四、生成的SQL脚本
CREATE TABLE
`address_11fk` (
五、映射方法:
在Person中添加Address属性,映射配置为: <!--用来映射关联PO column是Address在该表中的外键列名,增加unique变成“1-1”--> <many-to-one name="address11fk" column="addressId" unique="true"/>
Address11fk.hbm.xml: <hibernate-mapping>
Person11fk.hbm.xml: <hibernate-mapping> hibernate.cfg.xml: 在该配置文件的<session-factory></session-factory>标签中加入 <mapping resource= com.lavasoft.dx._n_1_fk. Addressn1fk.hbm.xml> <mapping resource= com.lavasoft.dx._n_1_fk. Personn1fk.hbm.xml >
六、测试方法
public class
Test_11fk {
七、测试结果
1) :正常保存. 推荐这么干! session.save(add1); session.save(p1);
Hibernate: insert into ADDRESS_11fk (addressdetail) values (?) Hibernate: insert into PERSON_11fk (name, age, addressId) values (?, ?, ?)
2) :正常保存. session.save(p1); session.save(add1);
Hibernate: insert into PERSON_11fk (name, age, addressId) values (?, ?, ?) Hibernate: insert into ADDRESS_11fk (addressdetail) values (?) Hibernate: update PERSON_11fk set name=?, age=?, addressId=? where personid=?
3) :正常保存. //session.save(p1); session.save(add1);
Hibernate: insert into ADDRESS_11fk (addressdetail) values (?)
4) : 发生异常,不能保存. session.save(p1); //session.save(add1);
Hibernate: insert into PERSON_11fk (name, age, addressId) values (?, ?, ?) Exception in thread "main" org.hibernate.TransientObjectException: com.lavasoft.dx._1_1_fk.Address11fk
5、one to many 这种情况很少见,但Hibernate同样允许采用连接表关联1-1.有连接表的1-1同样只需要将N-1的many-to-one元素增加unique="true"属性即可。
一、模型介绍
一个人(Person)对应多个地址(Address),比如家庭地址、公司地址。
二、实体(省略getter、setter方法)
public class Person1nfk implements Serializable { private int personid; private String name; private int age; private Set addresses=new HashSet();
public class Address1nfk implements Serializable { private int addressid; private String addressdetail;
三、表模型
mysql> desc address_1nfk; +---------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+--------------+------+-----+---------+----------------+ | addressid | int(11) | NO | PRI | NULL | auto_increment | | addressdetail | varchar(255) | YES | | NULL | | | personid | int(11) | YES | MUL | NULL | | +---------------+--------------+------+-----+---------+----------------+
mysql> desc person_1nfk; +----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+--------------+------+-----+---------+----------------+ | personid | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | age | int(11) | YES | | NULL | | +----------+--------------+------+-----+---------+----------------+
四、生成的SQL脚本
/* Formatted on 2007/08/21 10:06 (QP5 v5.50) */ CREATE TABLE `address_1nfk` ( `addressid` int(11) NOT NULL auto_increment, `addressdetail` varchar(255) default NULL, `addresses` int(11) default NULL, PRIMARY KEY (`addressid`), KEY `FK9B93456DC08D1667` (`addresses`), CONSTRAINT `FK9B93456DC08D1667` FOREIGN KEY (`addresses`) REFERENCES `person_1nfk` (`personid`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=gbk;
/* Formatted on 2007/08/21 10:07 (QP5 v5.50) */ CREATE TABLE `person_1nfk` ( `personid` int(11) NOT NULL auto_increment, `name` varchar(255) default NULL, `age` int(11) default NULL, PRIMARY KEY (`personid`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk;
五、映射方法:在实体类Person里面添加Address的集合,即可形成一对多关系。 <!--映射集合属性,关联到持久化类,inverse="false"表示主控端在Person1nfk端,lazy="false"表示不采用延迟加载--> <set name="addresses" table="ADDRESS_1nfk" cascade="all" > <!--确定关联的外键列--> <key column="personid"/> <!--用以映射到关联类属性--> <one-to-many class="com.lavasoft.dx._1_n_fk.Address1nfk"/> </set>
<hibernate-mapping> <class name="com.lavasoft.dx._1_n_fk.Person1nfk" table="PERSON_1nfk"> <id name="personid"> <generator class="identity"/> </id> <property name="name"/> <property name="age"/> <!--映射集合属性,关联到持久化类,inverse="false"表示主控端在Person1nfk端,lazy="false"表示不采用延迟加载--> <set name="addresses" table="ADDRESS_1nfk" cascade="all" > <!--确定关联的外键列--> <key column="personid"/> <!--用以映射到关联类属性--> <one-to-many class="com.lavasoft.dx._1_n_fk.Address1nfk"/> </set> </class> </hibernate-mapping>
<hibernate-mapping> <class name="com.lavasoft.dx._1_n_fk.Address1nfk" table="ADDRESS_1nfk"> <id name="addressid"> <generator class="identity"/> </id> <property name="addressdetail"/> </class> </hibernate-mapping>
六、测试方法
public class Test_1nfk { public static void main(String[] args){ Address1nfk add1=new Address1nfk(); Address1nfk add2=new Address1nfk(); Person1nfk p=new Person1nfk();
add1.setAddressdetail("郑州市经三路"); add2.setAddressdetail("合肥市宿州路"); p.setName("wang"); p.setAge(30); p.getAddresses().add(add1); p.getAddresses().add(add2);
Session session= HibernateUtil.getCurrentSession(); Transaction tx=session.beginTransaction(); session.save(add1); session.save(add2); session.save(p); tx.commit(); HibernateUtil.closeSession(); } }
七、测试结果
1) :正常保存. // session.save(add1); // session.save(add2); session.save(p); Hibernate: insert into PERSON_1nfk (name, age) values (?, ?) Hibernate: insert into ADDRESS_1nfk (addressdetail) values (?) Hibernate: insert into ADDRESS_1nfk (addressdetail) values (?) Hibernate: update ADDRESS_1nfk set personid=? where addressid=? Hibernate: update ADDRESS_1nfk set personid=? where addressid=?
2) :正常保存. session.save(add1); session.save(add2); session.save(p); Hibernate: insert into ADDRESS_1nfk (addressdetail) values (?) Hibernate: insert into ADDRESS_1nfk (addressdetail) values (?) Hibernate: insert into PERSON_1nfk (name, age) values (?, ?) Hibernate: update ADDRESS_1nfk set personid=? where addressid=? Hibernate: update ADDRESS_1nfk set personid=? where addressid=?
3) :正常保存. session.save(add1); session.save(add2); // session.save(p); Hibernate: insert into ADDRESS_1nfk (addressdetail) values (?) Hibernate: insert into ADDRESS_1nfk (addressdetail) values (?)
|
|
来自: 英昌知识汇聚馆 > 《hibernate》