标签:.net setuid 老师 size mil table 文件引入 16px 主键
一对多:
客户和联系人是一对多关系:
联系人在人际交流中担任着重要的角色,在销售过程中,我们通常不是在最开始就联系到有决策权的高管,而有可能是接电话的前台A、营销人员B、客服C、技术人员D等等。这些人都是我们与企业保持交流的联系人。他们对产品的支持态度决定了产品是否能够顺利推送到高管面前。
通常销售人员在跟进一个客户时,会有一个或者多个联系人,这些联系人所处的职位决定了他们的角色。
也就是说客户和联系人的关系是:
公司和公司员工的关系。
多对多:
一对一:
一对多映射配置:
以客户和联系人为例:客户是一,联系人是多。
第一步:创建两个实体类,客户和联系人:
第二步:让两个实体类之间互相表示。
一个客户可以对应多个联系人。
这里装载联系人,装载的容器用的是Set集合,而不是LinkedList,因为Set集合的特点是,值不能够重复。
一个联系人只能属于一个客户。
//客户的实体类:
public class Customer {
private Integer cid;
private String custName;
private String custLevel;
private String custSource;
private String custPhone;
private String custMobile;
private Set<LinkMan> linkMans=new HashSet<LinkMan>();
public Set<LinkMan> getLinkMans() {
return linkMans;
}
public void setLinkMans(Set<LinkMan> linkMans) {
this.linkMans = linkMans;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustMobile() {
return custMobile;
}
public void setCustMobile(String custMobile) {
this.custMobile = custMobile;
}
public Customer(String custName, String custLevel, String custSource, String custPhone,
String custMobile) {
super();
this.custName = custName;
this.custLevel = custLevel;
this.custSource = custSource;
this.custPhone = custPhone;
this.custMobile = custMobile;
}
public Customer() {
super();
}
@Override
public String toString() {
return "Customer [cid=" + cid + ", custName=" + custName + ", custLevel=" + custLevel + ", custSource="
+ custSource + ", custPhone=" + custPhone + ", custMobile=" + custMobile + "]";
}
}
//联系人实体类
public class LinkMan {
private Integer lid;
private String lname;
private String lgender;
private String lphone;
private Customer customer;
public Customer getCustomer() {
return customer;.
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public Integer getLid() {
return lid;
}
public void setLid(Integer lid) {
this.lid = lid;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getLgender() {
return lgender;
}
public void setLgender(String lgender) {
this.lgender = lgender;
}
public String getLphone() {
return lphone;
}
public void setLphone(String lphone) {
this.lphone = lphone;
}
public LinkMan() {
super();
// TODO Auto-generated constructor stub
}
public LinkMan(String lname, String lgender, String lphone) {
super();
this.lname = lname;
this.lgender = lgender;
this.lphone = lphone;
}
@Override
public String toString() {
return "LinkMan [lid=" + lid + ", lname=" + lname + ", lgender=" + lgender + ", lphone=" + lphone + "]";
}
}
第三步:配置映射关系
在客户的映射文件中,表示所有的联系人
<class name="类的全路径" table="表名">
<id name="id" column="cid">//实体类属性名以及表字段名
<generator class="native"></generator>
</id>
<property name="custName"></property>
<property name="custLevel"></property>
<property name="custSource"></property>
<property name="custPhone"></property>
<property name="custMobile"></property>
<!--
在客户映射文件中,表示所有联系人
使用set标签表示所有联系人
set标签里面有name属性:属性值写,在客户实体类里面表示联系人的set集合名称
-->
<set name="setLinkMan">
<!--
一对多建表,有外键
hibernate机制:双向维护外键,在一和多两方都配置外键。
column属性值:外键名称。这里的外键名称可以随便写。
-->
<key column="clid"></key>
<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
<one-to-many class="联系人实体类全路径" />
</set>
</class>
在联系人映射文件中,表示所属客户
<class name="实体类的全路径" table="表名">
<id name="lid"><!-- 当column不写时,名称和name的名称一样 -->
<generator class="native"></generator>
</id>
<property name="lname"></property>
<property name="lgender"></property>
<property name="lphone"></property>
<!--
表示联系人所属客户
name属性:联系人实体类被装载到Customer中,这里写customer名称
class属性:customer全路径
column属性:外键名称
-->
<many-to-one name="customer" class="customer全路径" column="clid"></many-to-one>
</class>
第四步:创建核心配置文件,把映射文件引入到核心配置文件中。
<mapping resource="cn/domarvel/entity/Customer.hbm.xml"/>
<mapping resource="cn/domarvel/entity/LinkMan.hbm.xml"/>
第五步:写测试类:
最后:运行项目,让表被创建。
可以看到结果,客户表和联系人表进行了关联,联系人引入客户表的id作为外键。
这些操作Hibernate都帮你封装好了。
级联操作
级联保存:
//在没有进行简化前,需要将联系人和客户的关系在代码行中进行说明。
@Test
public void showCreate(){
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
Customer customer=new Customer("百度", "vip", "网络", "110", "120");
LinkMan linkMan=new LinkMan("侯松", "男", "123");
customer.getLinkMans().add(linkMan);
linkMan.setCustomer(customer);//注意在没有进行配置简化配置的时候还需要让联系人实体类和客户实体类关联。
session.save(customer);
session.save(linkMan);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
简化操作:
在映射文件的客户方,也就是一对多的一这方进行配置:
<set name="linkMans" cascade="save-update"><!-- 这里配置了一个属性cascade,值为save-update,表示对保存和更新操作,做了简化,不用对多的那方
设置和一的那方的关系。 -->
<key column="clid"></key>
<one-to-many class="cn.domarvel.entity.LinkMan"/>
</set>
//简化后代码
@Test
public void showCreate02(){
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
Customer customer=new Customer("腾讯", "svip", "网络", "110", "120");
LinkMan linkMan=new LinkMan("FireLang", "女", "123");
customer.getLinkMans().add(linkMan);//注意在这里就只需要把联系人(多的那方)放入到客户方(一的那方),就可以了。
session.save(customer);//最后保存的时候就只需要保存客户方(一的那方)
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
级联删除:
这里就直接上简化后的代码了。
<!-- 配置映射文件 -->
<!-- 在一的那方配置删除的简化,当要想直接删除一的那方,Hibernate自动帮你删除相关联的多的那方 -->
<set name="linkMans" cascade="save-update,delete"><!-- 在cascade里面配置delete,多个值用","分割 -->
<key column="clid"></key>
<one-to-many class="cn.domarvel.entity.LinkMan"/>
</set>
//测试代码
@Test
public void showDelete(){
//在以前我们要删除一的那方,是先根据一的那方删除多的那方,再删除一的那方。
//现在Hibernate已经帮我们封装好了,我们只需要配置好,再直接删除一的那方就行了。
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
Customer customer=session.get(Customer.class, 2);
session.delete(customer);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
级联修改:
操作:现在是让一个联系人的客户变成另外一个。我们需要修改的就是某一个员工的外键值。
我们的普通更新操作:
@Test
public void showUpdate(){
//下面通过一个例子引入Hibernate中作更新操作时能够使用的一个关键字,目的是能够简化更新操作
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
Customer customer=session.get(Customer.class, 1);
LinkMan linkMan=session.get(LinkMan.class, 3);
linkMan.setCustomer(customer);//因为这里的数据是持久态的所以我们直接设置值后,Hibernate会帮我们自动更新数据。
customer.getLinkMans().add(linkMan);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
}
}
//通过输出底层sql代码可以知道
Hibernate:
select
customer0_.cid as cid1_1_0_,
customer0_.custName as custName2_1_0_,
customer0_.custLevel as custLeve3_1_0_,
customer0_.custSource as custSour4_1_0_,
customer0_.custPhone as custPhon5_1_0_,
customer0_.custMobile as custMobi6_1_0_
from
customer customer0_
where
customer0_.cid=?
Hibernate:
select
linkman0_.lid as lid1_2_0_,
linkman0_.lname as lname2_2_0_,
linkman0_.lgender as lgender3_2_0_,
linkman0_.lphone as lphone4_2_0_,
linkman0_.clid as clid5_2_0_
from
linkman linkman0_
where
linkman0_.lid=?
Hibernate:
select
linkmans0_.clid as clid5_2_0_,
linkmans0_.lid as lid1_2_0_,
linkmans0_.lid as lid1_2_1_,
linkmans0_.lname as lname2_2_1_,
linkmans0_.lgender as lgender3_2_1_,
linkmans0_.lphone as lphone4_2_1_,
linkmans0_.clid as clid5_2_1_
from
linkman linkmans0_
where
linkmans0_.clid=?
Hibernate:
update
linkman
set
lname=?,
lgender=?,
lphone=?,
clid=?
where
lid=?
Hibernate:
update
linkman
set
clid=?
where
lid=?
//在这里进行了重复的修改外键的操作,修改两次的原因是Hibernate双向维护外键。
inverse属性
linkMan.setCustomer(customer);
。达到了更新联系人所属关系。但是从上面的sql语句输出的情况可以看出。有两次的update操作。这两次是怎么来的呢???一次是我们自己写的。linkMan.setCustomer(customer);
另外一次是Hibernate帮我们修改外键关系的。所以这里就重复了update语句。使得修改关系时效率降低了。(注意:当我们修改多的那方的时候,不是修改的所属关系,而是其它的数据,那么就不会有两次更新。)那么我们该怎么解决更新两次的问题呢???那这里就得靠inverse属性了。解决方式:让其中的一方不维护外键。
具体实现:
在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性。(inverse:反向)
inverse:
//在这里不需要对java代码进行修改,只需要进行配置就可以了。这里还是用的是上面的问题代码。
//在一的一方进行配置,目的,不让一的一方反向维护
<set name="linkMans" cascade="save-update,delete" inverse="true">
<key column="clid"></key>
<one-to-many class="cn.domarvel.entity.LinkMan"/>
</set>
再次作关系更新操作,看一下运行结果:
Hibernate:
select
customer0_.cid as cid1_1_0_,
customer0_.custName as custName2_1_0_,
customer0_.custLevel as custLeve3_1_0_,
customer0_.custSource as custSour4_1_0_,
customer0_.custPhone as custPhon5_1_0_,
customer0_.custMobile as custMobi6_1_0_
from
customer customer0_
where
customer0_.cid=?
Hibernate:
select
linkman0_.lid as lid1_2_0_,
linkman0_.lname as lname2_2_0_,
linkman0_.lgender as lgender3_2_0_,
linkman0_.lphone as lphone4_2_0_,
linkman0_.clid as clid5_2_0_
from
linkman linkman0_
where
linkman0_.lid=?
Hibernate:
select
linkmans0_.clid as clid5_2_0_,
linkmans0_.lid as lid1_2_0_,
linkmans0_.lid as lid1_2_1_,
linkmans0_.lname as lname2_2_1_,
linkmans0_.lgender as lgender3_2_1_,
linkmans0_.lphone as lphone4_2_1_,
linkmans0_.clid as clid5_2_1_
from
linkman linkmans0_
where
linkmans0_.clid=?
Hibernate:
update
linkman
set
lname=?,
lgender=?,
lphone=?,
clid=?
where
lid=?
//可以看到这里update只更新了一次
//这里要注意:我们设置inverse=true,只是解决对更新所属关系时带来的效率问题。
这里有篇文章大家一定要看看(inverse和cascade的区别,以及一对多添加操作时外键为Null的问题)
多对多映射配置
第一步:创建实体类,用户和角色。
第二步:让两个实体类之间互相表示。
public class User {
private Integer uid;
private String uname;
private String pword;
private Set<Role> roleSet=new HashSet<Role>();
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPword() {
return pword;
}
public void setPword(String pword) {
this.pword = pword;
}
public Set<Role> getRoleSet() {
return roleSet;
}
public void setRoleSet(Set<Role> roleSet) {
this.roleSet = roleSet;
}
@Override
public String toString() {
return "User [uid=" + uid + ", uname=" + uname + ", pword=" + pword + ", roleSet=" + roleSet + "]";
}
public User() {
super();
// TODO Auto-generated constructor stub
}
public User( String uname, String pword, Role role) {
super();
this.uname = uname;
this.pword = pword;
roleSet.add(role);
}
}
public class Role {
private Integer rid;
private String rname;
private String rmemo;
private Set<Role> userSet=new HashSet<Role>();
public Set<Role> getUserSet() {
return userSet;
}
public void setUserSet(Set<Role> userSet) {
this.userSet = userSet;
}
public Integer getRid() {
return rid;
}
public void setRid(Integer rid) {
this.rid = rid;
}
public String getRname() {
return rname;
}
public void setRname(String rname) {
this.rname = rname;
}
public String getRmemo() {
return rmemo;
}
public void setRmemo(String rmemo) {
this.rmemo = rmemo;
}
@Override
public String toString() {
return "Role [rid=" + rid + ", rname=" + rname + ", rmemo=" + rmemo + "]";
}
public Role(String rname, String rmemo) {
super();
this.rname = rname;
this.rmemo = rmemo;
}
public Role() {
super();
// TODO Auto-generated constructor stub
}
}
第三步:配置映射关系
配置多对多关系
在用户里面表示所有角色,使用set标签
<?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="cn.domarvel.manytomany.Userb" table="userb">
<!-- table是要生成的表名 -->
<id name="uid">
<generator class="native"></generator>
</id>
<property name="uname"/>
<property name="pword"/>
<!-- property里面的column属性可以不用写,不写就默认和property里面的name属性值相同 -->
<set name="roleSet" table="user_role" cascade="save-update">
<!--
在用户里面表示角色,使用set标签
name属性:角色set集合名称
table属性:第三张表名称
-->
<!--
注意如果还没有在其它映射文件中配置表名,那么第一次配置就可以乱写,
但是如果有一张表已经声明说表名叫什么了,那就不能够再乱写
-->
<key column="fuid"/>
<!--
key标签里面配置:
配置当前映射文件在第三张表外键名称
-->
<many-to-many class="cn.domarvel.manytomany.Role" column="frid"></many-to-many>
<!--
class:角色实体类全路径
column:角色在第三张表外键名称
-->
</set>
</class>
</hibernate-mapping>
<?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="cn.domarvel.entity.Role" table="role">
<id name="rid">
<generator class="native"></generator>
</id>
<property name="rname"/>
<property name="rmemo"/>
<set name="userSet" table="user_role">
<key column="frid"></key>
<many-to-many class="cn.domarvel.entity.User" column="fuid"></many-to-many>
</set>
</class>
</hibernate-mapping>
第四步:在核心配置文件中引入映射文件
<?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>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<mapping resource="cn/domarvel/entity/Role.hbm.xml"/>
<mapping resource="cn/domarvel/entity/User.hbm.xml"/><!-- 引入映射配置文件到核心配置文件 -->
</session-factory>
</hibernate-configuration>
多对多级联保存
根据用户保存角色:
第一步:在用户配置文件中set标签进行配置,cascade值save-update,意思是对级联操作进行了简化,比如说:当我一对多的时候,我们以前是先删除多的那方再删除一的那方,或者先保存多的那方再保存一的那方。但是现在不用了如果我们设置了save-update或者delete,那我们只需要删除一的那方或者保存一的那方就行了,但前提是必须要先把多的那方保存到一的那方里面才可以使用。这也就是简化操作。
<set name="roleSet" table="user_role" cascade="save-update"><!-- 注意cascade是配置到哪儿里后,在保存的时候就保存哪儿一个被配置的实体。并且
另外一个实体就保存到被配置的实体里面。这里配置的是User所以就是根据User保存角色 -->
第二步:写代码实现
@Test
public void showAddManyToM(){
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
User user=new User("LangSheng", "123456",new Role("开发工程师", "专注于网页前后台开发,和图像算法!!"));
user.getRoleSet().add(new Role("架构师", "进行程序开发架构!"));
User user2=new User("FireLang", "456123", new Role("狼神总部副总裁", "国际知名企业!!"));
user2.getRoleSet().add(new Role("图像算法师", "通过代码对程序的算法处理!以及识别!!"));
session.save(user);
session.save(user2);
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
}
多对多级联删除
对于级联删除
在完成上面级联删除的操作后,对于级联删除就变得很简单了。
第一步:在set标签中配置cascade属性,值为delete;如果有多个值记得用”,”号隔开,比如cascade=”save-update,delete”;
第二步:直接进行删除。
对于级联删除,在我们一对多的时候还可以用,也挺方便的。但是在我们的多对多的里面就显得有些鸡肋了,因为,假如我们删除用户表里面的某个用户,那么就会把该用户和角色表里面属于该用户角色属性的角色以及第三张表涉及到该用户的都会删掉。而我们一般角色是不能够删除的,因为有可能其它用户还有该角色,如果你把别人的角色删掉了,那么其它用户和该角色在第三张表中的关系也会被删掉的。
所以我们不推荐使用级联删除来操作多对多关系。
我们应该做的是维护第三张表,也就是用户和角色的主键组成的一个外建表。
维护第三张表关系
用户和角色多对多关系,维护关系通过第三张表维护
让某个用户有某个角色
第一步:根据id查询用户和角色
第二步:把角色放到用户里面
@Test
public void showCreateRelation(){
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
User user=session.get(User.class, 4);
Role role=session.get(Role.class, 6);
user.getRoleSet().add(role);
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
}
让某个用户没有某个角色
@Test
public void showRemoveReation(){
Transaction transaction=null;
try {
Session session=HibernateUtils.getCurrentSession();
transaction=session.beginTransaction();
User user=session.get(User.class, 4);
Role role=session.get(Role.class, 6);
user.getRoleSet().remove(role);
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Marvel__Dead/article/details/62416415
标签:.net setuid 老师 size mil table 文件引入 16px 主键
原文地址:https://www.cnblogs.com/satisfysmy/p/9086140.html