今天我们来一起谈论下hibernate的基于主键的单项,双向多对多映射关系
首先多对多都是基于主键的,没有基于外键的说法
1.基于主键的单项多对多
在这里就是说中间stuobject是一张关系表,将两张表的主键进行关联,形成了多对多的关系
代码如下:
public class StuObject {
private int stuobjectid;
private String objectname;
private StuObject(){}
public StuObject(String objectname){
this.objectname=objectname;
}
public int getStuobjectid() {
return stuobjectid;
}
public void setStuobjectid(int stuobjectid) {
this.stuobjectid = stuobjectid;
}
public String getObjectname() {
return objectname;
}
public void setObjectname(String objectname) {
this.objectname = objectname;
}
}
public class YoungStu {
private int stuid;
private String youngname;
private Set<StuObject> stuobject;
public YoungStu(){
}
public YoungStu(String youngname){
this.youngname=youngname;
}
public int getStuid() {
return stuid;
}
public void setStuid(int stuid) {
this.stuid = stuid;
}
public String getYoungname() {
return youngname;
}
public void setYoungname(String youngname) {
this.youngname = youngname;
}
public Set<StuObject> getStuobject() {
return stuobject;
}
public void setStuobject(Set<StuObject> stuobject) {
this.stuobject = stuobject;
}
}
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
session:会话 当前调用者与数据库之间的一个连接
factory:工厂
其他概念:
struts2中的session是指当前用户与服务器之间的一个连接
-->
<session-factory>
<!-- 配置数据库连接信息 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property><!-- 数据库驱动 -->
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate4</property><!--数据库地址 -->
<property name="connection.username">**</property><!-- 用户名 -->
<property name="connection.password">****</property><!-- 密码 -->
<!--
dialect数据库方言:指明用什么数据库
driver_class指定的是引用的驱动
两者不是一码事
-->
<!--
dialect:指连接什么数据库
connection.driver_class:连接数据库所需要的驱动
-->
<property name="dialect">
org.hibernate.dialect.MySQL5Dialect
</property>
<!-- 是否打印sql -->
<property name="show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="format_sql">true</property>
<mapping resource="hibernatedemo1/pojo/stuobject.hbm.xml"></mapping>
<mapping resource="hibernatedemo1/pojo/Youngstu.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
youngstu.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hibernatedemo1.pojo.YoungStu" table="youngstu">
<!--
id标签必须有
id:主键只是hibernate在操作数据库表的时候的一个概念,并不要求此列也为数据库规范意义上的主键
-->
<!-- id标签对应的是实体类的属性,表中可以没有主键-->
<id name="stuid">
<!--
generator:主键生成策略
native:自增长(映射文件生成策略为native,且表中相应的列设为自增)
assigned:自定义(如果此列在数据库中是主键的话,那么程序在save时,必须保证此列对应的对象属性有值)
increment:由hibernate从数据库中取出主键的最大值(每个session只取一次),以该值为基础,每次增量为1,在内存 中生成主键
不依赖于底层的数据库,因此可以跨数据库
sequence:采用数据库提供的sequence机制生成主键,需要数据库支持sequence
所以:native和sequence都有各自的数据库选型的局限性
-->
<generator class="increment"></generator>
</id>
<!--这里的name必须和映射类里的字段名一致-->
<property name="youngname"/>
<!--这里的name是你映射类里的set的别名 后面是重新建立一个关系表-->
<set name="stuobject" table="stuobject">
<!--**表示当前类映射到关系表stuobject中的列,这个column是table所指引的列名,不一定要和映射类里的id名称一样**-->
<key column="stuid"></key>
<!--所对应的另一个表(与yongstu产生关系的一方) column是table所指引的列名,不一定要和映射类里的id名称一样-->
<many-to-many class="hibernatedemo1.pojo.StuObject" column="stuobjectid"></many-to-many>
</set>
</class>
</hibernate-mapping>
stuobject.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hibernatedemo1.pojo.StuObject" table="object">
<!--
id标签必须有
id:主键只是hibernate在操作数据库表的时候的一个概念,并不要求此列也为数据库规范意义上的主键
-->
<!-- id标签对应的是实体类的属性,表中可以没有主键-->
<id name="stuobjectid">
<!--
generator:主键生成策略
native:自增长(映射文件生成策略为native,且表中相应的列设为自增)
assigned:自定义(如果此列在数据库中是主键的话,那么程序在save时,必须保证此列对应的对象属性有值)
increment:由hibernate从数据库中取出主键的最大值(每个session只取一次),以该值为基础,每次增量为1,在内存 中生成主键
不依赖于底层的数据库,因此可以跨数据库
sequence:采用数据库提供的sequence机制生成主键,需要数据库支持sequence
所以:native和sequence都有各自的数据库选型的局限性
-->
<generator class="increment"></generator>
</id>
<property name="objectname"/>
</class>
</hibernate-mapping>
测试代码
HibernateUtil.java
public class HibernateUtil {
private static final Configuration cfg;
private static final SessionFactory sessionFactory;
static{
cfg = new Configuration().configure();
ServiceRegistry registry = new StandardServiceRegistryBuilder()
.applySettings(cfg.getProperties()).build();
sessionFactory=cfg.buildSessionFactory(registry);
}
public static Session openSession(){
return sessionFactory.openSession();
}
}
Demo.java
//基于主键的单项多对多映射
@Test
public void fkmanytomanyTest(){
Session session=HibernateUtil.openSession();
Transaction tx=session.beginTransaction();
YoungStu youngstu=new YoungStu("Align");
session.saveOrUpdate(youngstu);
youngstu.setStuobject(new HashSet());
for(int i=0;i<5;i++){
StuObject stuobject=new StuObject("高数"+i);
youngstu.getStuobject().add(stuobject);
session.saveOrUpdate(stuobject);
}
tx.commit();
session.close();
}
2.双向多对多映射关系
Role.java
public class Role {
private int id;
private String name;
private Set<Function> function;
public Role(){}
public Role(String name){
this.name=name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Function> getFunction() {
return function;
}
public void setFunction(Set<Function> function) {
this.function = function;
}
}
Function.java
public class Function {
private int funid;
private String code;
private String url;
private Set<Role> role;
public Function(){}
public Function(String code,String url){
this.code=code;
this.url=url;
}
public int getFunid() {
return funid;
}
public void setFunid(int funid) {
this.funid = funid;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Set<Role> getRole() {
return role;
}
public void setRole(Set<Role> role) {
this.role = role;
}
}
role.hbm.xml
<hibernate-mapping>
<class name="hibernatedemo1.pojo.Role" table="role">
<id name="id">
<generator class="increment"></generator>
</id>
<property name="name"/>
<set name="function" table="rolefunction">
<key column="roleid"></key>
<many-to-many class="hibernatedemo1.pojo.Function" column="funid"></many-to-many>
</set>
</class>
</hibernate-mapping>
function.hbm.xml
<hibernate-mapping>
<class name="hibernatedemo1.pojo.Function" table="function">
<id name="funid">
<generator class="increment"></generator>
</id>
<property name="code"/>
<property name="url"></property>
<set name="role" table="rolefunction">
<key column="funid"></key>
<many-to-many class="hibernatedemo1.pojo.Role" column="roleid"></many-to-many>
</set>
</class>
</hibernate-mapping>
这两个hbm.xml里面要注意
<set name="function" table="rolefunction">
<key column="roleid"></key>
<many-to-many class="hibernatedemo1.pojo.Function" column="funid"></many-to-many>
</set>
<!--这两个里面的column一定要一一对应,不能随便-->
<set name="role" table="rolefunction">
<key column="funid"></key>
<many-to-many class="hibernatedemo1.pojo.Role" column="roleid"></many-to-many>
</set>