http://blog.csdn.net/yerenyuan_pku/article/details/70152173

Hibernate关联映射——一对多(多对一)

我们以客户(Customer)与订单(Order)为例来讲解Hibernate关联映射中的一对多关联关系。 
首先肯定是搭建好Hibernate的开发环境,我在此也不过多赘述,读者自行实践。接着在src目录下创建一个cn.itheima.oneToMany包,并在该包下创建两个实体类,如下:

  • 客户类

    // 客户 ---- 一的一方
    public class Customer { private Integer id; // 主键
    private String name; // 姓名 // 描述客户可以有多个订单
    private Set<Order> orders = new HashSet<Order>(); public Set<Order> getOrders() {
    return orders;
    }
    public void setOrders(Set<Order> orders) {
    this.orders = orders;
    }
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    } }
    • 1
  • 订单类

    // 订单 ---- 多的一方
    public class Order { private Integer id;
    private Double money;
    private String receiverInfo; // 收货地址 // 订单与客户关联
    private Customer c; // 描述订单属于某一个客户 public Customer getC() {
    return c;
    }
    public void setC(Customer c) {
    this.c = c;
    }
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }
    public Double getMoney() {
    return money;
    }
    public void setMoney(Double money) {
    this.money = money;
    }
    public String getReceiverInfo() {
    return receiverInfo;
    }
    public void setReceiverInfo(String receiverInfo) {
    this.receiverInfo = receiverInfo;
    } }
    • 1

完成之后,再在cn.itheima.oneToMany包下分别编写这两个类的映射配置文件。

  • Customer.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="cn.itheima.oneToMany.Customer" table="t_customer">
    <id name="id" column="c_id">
    <generator class="identity" />
    </id>
    <property name="name" column="c_name" length="20" /> <!-- 一个客户关联多个订单 -->
    <!--
    使用set来描述在一的一方中关联的多,也即Set<Order>
    它的name属性就是Set集合的名称:orders
    key:它主要描述关联的多的一方产生的外键名称,注意要与多的一方定义的外键名称相同
    one-to-many:主要描述集合中的类型
    -->
    <set name="orders">
    <key column="c_customer_id" />
    <one-to-many class="cn.itheima.oneToMany.Order" />
    </set>
    </class>
    </hibernate-mapping>
    • 1
  • Order.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="cn.itheima.oneToMany.Order" table="t_order">
    <id name="id" column="c_id">
    <generator class="identity" />
    </id>
    <property name="money" column="c_money" />
    <property name="receiverInfo" column="c_receiverInfo" length="50" />
    <!-- 多对一 -->
    <!--
    name属性它描述的是Order类中的一的一方的属性名称:Customer c;
    class属性代表的是一的一方的类型
    column属性描述的是一对多,在多的一方产生的外键的名称:c_customer_id
    -->
    <many-to-one name="c" class="cn.itheima.oneToMany.Customer" column="c_customer_id">
    </many-to-one>
    </class>
    </hibernate-mapping>
    • 1

测试双向关联保存

现在我们来测试保存的操作,在src目录下创建一个cn.itheima.test包,并在该包下编写一个OneToManyTest单元测试类,然后在该类中编写一个用于测试保存的操作,如下:

public class OneToManyTest {

    // 测试保存,如果我做的是双向的关联,没有用cascade去做级联,那么就存在一个浪费的环节。
@Test
public void test1() { // 1.得到Session
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.操作
// 2.1创建客户
Customer c = new Customer();
c.setName("张三"); // 2.2创建两个订单
Order o1 = new Order();
o1.setMoney(1000d);
o1.setReceiverInfo("武汉"); Order o2 = new Order();
o2.setMoney(2000d);
o2.setReceiverInfo("上海"); // 2.3建立关系
// 2.3.1订单关联客户
o1.setC(c);
o2.setC(c);
// 2.3.2客户关联订单
c.getOrders().add(o1);
c.getOrders().add(o2); session.save(o1);
session.save(o2);
session.save(c); // 3.事务提交,并关闭session
session.getTransaction().commit();
session.close();
} }

测试test1方法,运行正常。其实上面测试保存的操作就是一种双向关联关系,如果做的是双向的关联,而没有用cascade去做级联,那么就存在一个浪费的环节,后面会讲。 
顺其自然地,我们就会想可不可以只保存订单或只保存客户就能完成保存的操作呢?答案是不言而喻的。下面我就来简单地讲讲。

测试单向关联保存

现在我们只想保存订单,然后顺便保存客户,可以预想到的是我们可能会这样写代码:

public class OneToManyTest {

    // 测试保存 --- 单向操作(只演示保存订单,然后顺便保存客户)
@Test
public void test2() { // 1.得到Session
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.操作
// 2.1创建客户
Customer c = new Customer();
c.setName("张三"); // 2.2创建两个订单
Order o1 = new Order();
o1.setMoney(1000d);
o1.setReceiverInfo("武汉"); Order o2 = new Order();
o2.setMoney(2000d);
o2.setReceiverInfo("上海"); // 2.3建立关系
// 2.3.1订单关联客户
o1.setC(c);
o2.setC(c); session.save(o1); // 这时o1是一个持久化对象
session.save(o2); // 这时o2也是一个持久化对象,而我们的o1和o2也关联了Customer对象,又Customer对象是一个瞬时对象,所以
// 在这时操作时,会报异常。 // 3.事务提交,并关闭session
session.getTransaction().commit();
session.close();
} }

这时测试以上方法,会发现报如下异常:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.itheima.oneToMany.Customer
at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:279)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:455)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:281)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:291)
at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:296)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:4081)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:532)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:215)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:142)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at cn.itheima.test.OneToManyTest.test2(OneToManyTest.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
  • 1

这个异常代表一个持久化对象关联了一个瞬时对象。出现问题,就要着手解决,那又怎么解决呢?我们可以使用级联操作来解决上述的问题,我们现在要做的是保存订单时保存客户,那么需要在订单类的映射配置文件中进行修改:

<many-to-one name="c" class="cn.itheima.oneToMany.Customer" column="c_customer_id" cascade="save-update"></many-to-one>

设置了cascade=save-update,那么在保存订单时就可以自动将客户保存了。这时再次执行test2方法,发现一切正常。 
现在我们又想要在完成保存客户时,保存订单,那又该怎么做呢?答案是不言而喻的,用屁股想都能知道,在客户类的映射配置文件中进行修改:

<set name="orders" cascade="save-update">
<key column="c_customer_id" />
<one-to-many class="cn.itheima.oneToMany.Order" />
</set>

设置了cascade=save-update,那么在保存客户时就可以自动将订单保存了。这时我们在OneToManyTest单元测试类再编写一个方法进行测试:

public class OneToManyTest {

    // 测试保存 --- 单向操作(保存客户并自动保存订单)
@Test
public void test3() { // 1.得到Session
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.操作
// 2.1创建客户
Customer c = new Customer();
c.setName("张三"); // 2.2创建两个订单
Order o1 = new Order();
o1.setMoney(1000d);
o1.setReceiverInfo("武汉"); Order o2 = new Order();
o2.setMoney(2000d);
o2.setReceiverInfo("上海"); // 2.3建立关系
// 2.3.1客户与订单的关联
c.getOrders().add(o1);
c.getOrders().add(o2); session.save(c); // 保存客户 // 3.事务提交,并关闭session
session.getTransaction().commit();
session.close();
} }

双向关联维护

我们在开发中要配置双向关联配置,这样就可以通过任意一方来操作对方。但在写操作代码时,尽量要进行单向关联,这样可以尽量减少资源浪费。在前面测试双向关联保存那一小节中,我讲到存在一个资源浪费的问题,在这一节我就会细讲。 
回到最初测试双向关联保存的位置,如果像那样测试test1方法,那么Eclipse控制台会打印如下sql语句:

Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_customer
(c_name)
values
(?)
-------------------------自己加的分割线-------------------------------
Hibernate:
update
t_order
set
c_money=?,
c_receiverInfo=?,
c_customer_id=?
where
c_id=?
Hibernate:
update
t_order
set
c_money=?,
c_receiverInfo=?,
c_customer_id=?
where
c_id=?
Hibernate:
update
t_order
set
c_customer_id=?
where
c_id=?
Hibernate:
update
t_order
set
c_customer_id=?
where
c_id=?

发现有4条update语句,为什么会这样昵?原因非常简单,我们现在这个操作,是做了一个双向关联,那么订单和客户都会去维护c_customer_id这个 
外键,也就是说当我们插订单的时候,c_customer_id是没值的,因为还没有Customer,所以它插入的是一个null值。当我们插完订单以后,再去插入客户, 
客户有了,我们就需要对订单里面的c_customer_id去修改,所以就会出现这样一种情况。 
在双向关联中,会存在多余的update语句,这个存在虽然不影响我们的程序运行,但是会影响性能,因为它在浪费资源。所以在写操作代码时,尽量要进行单向关联,但如果我们非得进行双向关联呢?那又该怎么减少资源浪费呢?这时我们可以使用inverse属性来设置,双向关联时由哪一方来维护表与表之间的关系。通常我们都会在多的一方维护关联关系,所以最好由订单类来维护双向关联关系,那么客户类的映射配置文件应修改为:

<set name="orders" inverse="true">
<key column="c_customer_id" />
<one-to-many class="cn.itheima.oneToMany.Order" />
</set>
  • inverse的值如果为true,代表由对方来维护外键。
  • inverse的值如果为false,代表由本方来维护外键。

关于inverse的取值有这样一个原则:外键在哪一个表中,我们就让哪一方来维护外键。 
就这样简简单单修改之后,再次测试test1方法,Eclipse控制台会打印如下sql语句:

Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_customer
(c_name)
values
(?)
-------------------------自己加的分割线-------------------------------
Hibernate:
update
t_order
set
c_money=?,
c_receiverInfo=?,
c_customer_id=?
where
c_id=?
Hibernate:
update
t_order
set
c_money=?,
c_receiverInfo=?,
c_customer_id=?
where
c_id=?
  • 1

可发现update语句是少了两条的。

一对多的对象导航

下面来看看一对多的对象导航问题,如图: 

下面我们编写代码来进行演示,在OneToManyTest单元测试类编写如下测试方法:

public class OneToManyTest {

    // 测试一对多导航问题
@Test
public void test4() {
// 1.得到Session
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 操作
// 2.1创建客户
Customer c = new Customer();
c.setName("张三"); // 2.2创建两个订单
Order o1 = new Order();
o1.setMoney(1000d);
o1.setReceiverInfo("武汉"); Order o2 = new Order();
o2.setMoney(2000d);
o2.setReceiverInfo("上海"); Order o3 = new Order();
o3.setMoney(3000d);
o3.setReceiverInfo("天门"); // 描述关系
// o1要关联上c
o1.setC(c); // c要关联上o2、o3
c.getOrders().add(o2);
c.getOrders().add(o3); session.save(o1); // 3.事务提交,并关闭session
session.getTransaction().commit();
session.close();
} }

运行以上方法,可发现Eclipse控制台打印出如下sql语句:

Hibernate:
insert
into
t_customer
(c_name)
values
(?)
Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)
Hibernate:
insert
into
t_order
(c_money, c_receiverInfo, c_customer_id)
values
(?, ?, ?)

所以共插入4条记录。其他情况请读者自行测试。

级联删除

现在我们有这样一个需求:当我们删除一个客户时,应该将客户对应的订单也删除(实际开发中删除订单时,是不需要删除客户的)。首先查看一下客户类和订单类的映射配置文件:

  • Customer.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="cn.itheima.oneToMany.Customer" table="t_customer">
    <id name="id" column="c_id">
    <generator class="identity" />
    </id>
    <property name="name" column="c_name" length="20" /> <!-- 一个客户关联多个订单 -->
    <!--
    使用set来描述在一的一方中关联的多,也即Set<Order>
    它的name属性就是Set集合的名称:orders
    key:它主要描述关联的多的一方产生的外键名称,注意要与多的一方定义的外键名称相同
    one-to-many:主要描述集合中的类型
    -->
    <set name="orders" inverse="true" cascade="save-update">
    <key column="c_customer_id" />
    <one-to-many class="cn.itheima.oneToMany.Order" />
    </set>
    </class>
    </hibernate-mapping>
  • Order.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    <class name="cn.itheima.oneToMany.Order" table="t_order">
    <id name="id" column="c_id">
    <generator class="identity" />
    </id>
    <property name="money" column="c_money" />
    <property name="receiverInfo" column="c_receiverInfo" length="50" />
    <!-- 多对一 -->
    <!--
    name属性它描述的是Order类中的一的一方的属性名称:Customer c;
    class属性代表的是一的一方的类型
    column属性描述的是一对多,在多的一方产生的外键的名称:c_customer_id
    -->
    <many-to-one name="c" class="cn.itheima.oneToMany.Customer" column="c_customer_id" cascade="save-update">
    </many-to-one>
    </class>
    </hibernate-mapping>
    • 1

大家的映射配置文件是不是上面这样的,如果是的话,可以在OneToManyTest单元测试类编写一个方法进行测试:

public class OneToManyTest {

    @Test
public void test5() {
// 1.得到Session
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 操作 → 删除订单时,不需要删除客户;当我们删除一个客户时,应该将客户对应的订单也删除
Customer c = session.get(Customer.class, 1); session.delete(c); // 删除客户,订单是否会删除昵? // 3.事务提交,并关闭session
session.getTransaction().commit();
session.close();
} }

我们在删除客户时,也要删除订单,如果没有做级联删除的话,那么这个操作是不被允许的,原因是为了维护数据完整性。如果我们想要完成操作,可以在客户类的映射文件中添加cascade="delete",如下:

<set name="orders" inverse="true" cascade="delete">
<key column="c_customer_id" />
<one-to-many class="cn.itheima.oneToMany.Order" />
</set>

delete-orphan用法

delete-orphan(删除孤儿) :删除与当前对象解除关系的对象。 
现举例来演示delete-orphan的用法,在OneToManyTest单元测试类编写如下一个方法:

public class OneToManyTest {

    @Test
public void test6() {
// 1.得到Session
Session session = HibernateUtils.openSession();
session.beginTransaction(); // 2.操作
// 得到客户
Customer c = session.get(Customer.class, 1);
// 得到客户的一个订单
Order o = session.get(Order.class, 1); c.getOrders().remove(o); // 从集合里面移除掉一个订单,能实现这个效果吗?不能 // 3.事务提交,并关闭session
session.getTransaction().commit();
session.close();
} }
  • 1

这时运行以上方法,发现id为1的订单并没有被删除。如果想起到我们预期的效果,可以在客户类的映射文件中添加cascade="delete-orphan",如下:

<set name="orders" inverse="true" cascade="delete-orphan">
<key column="c_customer_id" />
<one-to-many class="cn.itheima.oneToMany.Order" />
</set>

cascade总结

使用cascade可以完成级联操作,它的常用可取值:

  • none:这是一个默认值
  • save-update:当我们配置它时,底层使用save、update或saveOrUpdate完成操作,级联保存临时对象,如果是游离对象,会执行update
  • delete:级联删除
  • delete-orphan:删除与当前对象解除关系的对象
  • all:它包含了save-update、delete操作
  • all-delete-orphan:它包含了delete-orphan与all操作

(转)Hibernate关联映射——一对多(多对一)的更多相关文章

  1. Hibernate关联映射(单项多对一和一对多、双向一对多)

    最近总是接触着新的知识点来扩展自己的知识面:不停的让自己在原地接触天空的感觉真的很美好!!!革命没有成功,程序员的我们怎么能不努力呢...... 一.用员工和部门来剖析关联映射的原理. 1)从这张截图 ...

  2. Hibernate 集合映射 一对多多对一 inverse属性 + cascade级联属性 多对多 一对一 关系映射

    1 . 集合映射 需求:购物商城,用户有多个地址. // javabean设计 // javabean设计 public class User { private int userId; privat ...

  3. Hibernate关联映射之_多对一

    多对一 Employee-Department 对于 员工 和 部门 两个对象,从员工的角度来看,就是多对一的一个关系--->多个员工对应一个部门 表设计: 部门表:department,id主 ...

  4. Hibernate关联映射(一对多/多对多)

    版权声明:翀版 https://blog.csdn.net/biggerchong/article/details/843401053.  Hibernate关联映射上接Hibernate持久化类:h ...

  5. Java三大框架之——Hibernate关联映射与级联操作

    什么是Hibernate中的关联映射? 简单来说Hibernate是ORM映射的持久层框架,全称是(Object Relational Mapping),即对象关系映射. 它将数据库中的表映射成对应的 ...

  6. Hibernate关联映射关系

    Hibernate关联映射关系 一.双向一对多关联映射关系:当类与类之间建立了关联,就可以方便的从一个对象导航到另一个或另一组与它关联的对象(一对多双向关联和多对一双向关联是完全一样的) 1.1创建实 ...

  7. 第六章 Hibernate关联映射

    第六章 hibernate关联映射一.本章知识点分为2部分:1.关联关系:单向多对一关联关系,双向一对多关联关系(含一对多关联关系),多对多关联关系2.延迟加载:类级别加载策略,一对多加载策略,多对一 ...

  8. 【学习笔记】Hibernate关联映射(Y2-1-6)

    Hibernate关联映射 关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用. 1.单向多对一关联 准备数据库 部门表和员工表 其中部门表有两列 部门编号和名称 员工表有三列 员工 ...

  9. 第三章Hibernate关联映射

    第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...

随机推荐

  1. Oracle中的 row_number() over (partition by order by ) 用法

    oracle 里面经常这样用 select col1,col2..., row_number() over (partition by colx order by coly) from table_n ...

  2. ojdbc.jar

    Oracle的jdbc驱动是ojdbc.jar 文件,那么mysql的jdbc驱动是什么呢? 匿名 | 浏览 689 次 发布于2015-06-07 02:06   最佳答案   MySQL的JDBC ...

  3. ADO连接ACCESS2007及以上版本的数据库

    function getaccessstr(databasename:string;password:string;accessVer:string='access2003'):string; beg ...

  4. Display certain line(s) from a text file in Linux.

    Purpose: Display certain line or lines from a text file, such as : Display the 1000th line from file ...

  5. 用Arduino对Apple手表进行远程红外控制

    描写叙述 用于控制随意红外设备的Apple手表及iPhone应用. IOS应用发送HTTP请求至一个或多个带有以太网插板的Arduino.Arduino正在解析http请求并发送红外信号.Arduin ...

  6. Ambari-Blueprint介绍

    Ambari-Blueprint总体介绍 ambari-blueprint主要作用是通过提供一个restAPI.调用几次API就能够创建一个集群.ambari-server解析stack下的role_ ...

  7. Android-spinner

    Android-spinner 一 Adapter概念 spinner:下拉栏里面的TextView 指定系统spinner:在xml文件中面的spinner中的属性android:entries=& ...

  8. Wireshark 抓包遇到 you don’t have permission to capture on that device mac 错误的解决方案

    Wireshark 抓包遇到 you don’t have permission to capture on that device mac 错误的解决方案 上次有篇博客讲了如何利用wireshark ...

  9. Android 自己定义Activity基类

    我们在开发App的时候有时候碰到多个界面有一个共同点的时候.比方,都有同样的TitleBar.而且TitleBar能够设置显示的文字.TitleBar上的点击事件,假设给每个Activity都写一遍T ...

  10. wepack使用

    当前使用的版本:webpack 4.5. ⚠️webpack 是需要有 node 环境的,所以在使用之前需要保证你当前安装的有 node. 安装 webpack: npm install webpac ...