hibernate系列之四

数据库中表之间的关系:

一对一、一对多、多对多

 

 

一对多的建表原则:在多的一方创建外键指向一的一方的主键;

多对多的建表原则:创建一个中间表,中间表中至少有两个字段作为外键分别指向多对多双方的主键;

一对一建表原则:唯一外键对应:假设一对一中的任意一方为多,在多的一方创建外键指向一的一方的主键,将外键设置为唯一

      主键对应:一方的主键作为另一方的主键;

在hibernate中采用java对象关系描述数据表之间的关系:

一对多的映射关系的实现案例:

客户实体类:在hibernate系列一中已经实现点击连接查看:https://www.cnblogs.com/wang-xuan/p/9195795.html

同时在客户实体类中添加属性:

//一个客户对应多个联系人
	private Set<LinkMan> linkMans = new HashSet<LinkMan>();
public Set<LinkMan> getLinkMans() {
		return linkMans;
	}
	public void setLinkMans(Set<LinkMan> linkMans) {
		this.linkMans = linkMans;
	}

 

实现联系人实体类LinkMan:

package com.itwx.hibernate.pojo;

public class LinkMan {

	private Long lkm_id;
	private String lkm_name;
	private String lkm_gender;
	private String lkm_phone;
	private String lkm_mobile;
	private String lkm_email;
	private String lkm_qq;
	private String lkm_position;
	private String lkm_memo;
	
	private Customer customer;

	public Long getLkm_id() {
		return lkm_id;
	}

	public void setLkm_id(Long lkm_id) {
		this.lkm_id = lkm_id;
	}

	public String getLkm_name() {
		return lkm_name;
	}

	public void setLkm_name(String lkm_name) {
		this.lkm_name = lkm_name;
	}

	public String getLkm_gender() {
		return lkm_gender;
	}

	public void setLkm_gender(String lkm_gender) {
		this.lkm_gender = lkm_gender;
	}

	public String getLkm_phone() {
		return lkm_phone;
	}

	public void setLkm_phone(String lkm_phone) {
		this.lkm_phone = lkm_phone;
	}

	public String getLkm_mobile() {
		return lkm_mobile;
	}

	public void setLkm_mobile(String lkm_mobile) {
		this.lkm_mobile = lkm_mobile;
	}

	public String getLkm_email() {
		return lkm_email;
	}

	public void setLkm_email(String lkm_email) {
		this.lkm_email = lkm_email;
	}

	public String getLkm_qq() {
		return lkm_qq;
	}

	public void setLkm_qq(String lkm_qq) {
		this.lkm_qq = lkm_qq;
	}

	public String getLkm_position() {
		return lkm_position;
	}

	public void setLkm_position(String lkm_position) {
		this.lkm_position = lkm_position;
	}

	public String getLkm_memo() {
		return lkm_memo;
	}

	public void setLkm_memo(String lkm_memo) {
		this.lkm_memo = lkm_memo;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	
}

 配置LinkMan.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="com.itwx.hibernate.pojo.LinkMan" table="linkman">
		<id name="lkm_id" column="lkm_id">
			<generator class="native" />
		</id>
		<property name="lkm_name" column="lkm_name" />
		<property name="lkm_gender" column="lkm_gender" />
		<property name="lkm_phone" column="lkm_phone" />
		<property name="lkm_mobile" column="lkm_mobile" />
		<property name="lkm_email" column="lkm_email" />
		<property name="lkm_qq" column="lkm_qq" />
		<property name="lkm_position" column="lkm_position" />
		<!-- 配置关联对象 -->
		<!--  
			many-to-one:代表多对一:
				name属性:在实体类中的属性:一的一方的对象的名称;
				class属性:一的一方的类的全路径
				column:表中的外键,在一的一方中配置的外键;
		-->
		<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
			column="lkm_cust_id" />
	</class>
</hibernate-mapping>

 核心配置文件hibernate.cfg.xml

<!-- 配置加载映射文件:全路径-->
			<mapping resource="com/itwx/hibernate/pojo/Customer.hbm.xml"/>
			<mapping resource="com/itwx/hibernate/pojo/LinkMan.hbm.xml"/>

 Customer.hbm.xml配置文件添加一对多的关系映射配置

<!-- 配置多一之间的映射关系 -->
    	<!-- 
    		set标签:name属性:在实体类中的属性,指多的一方的集合的属性名称
    		key标签:column:多的一方的外键的名称
    		one-to-many标签:class属性:多的一方的类的全路径
    	-->
		<set name="linkMans">
			<key column="lkm_cust_id" />
			<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
		</set>

 测试类中进行测试一对多的关系映射

@Test
	public void test4() {
		// 获取当前与线程绑定的session
		Session session = HibernateUtils.getCurrentSession();
		// 开启事务
		Transaction transaction = session.beginTransaction();
		// 创建关系对象
		Customer customer = new Customer();// 此处可以使用带参构造方法
		customer.setCust_name("张三");
		customer.setCust_source("产品");

		LinkMan linkMan1 = new LinkMan();
		linkMan1.setLkm_name("周芷若");
		linkMan1.setLkm_phone("1223445");
		LinkMan linkMan2 = new LinkMan();
		linkMan2.setLkm_name("张无忌");
		linkMan2.setLkm_gender("男");
		// 建立关系
		/**
		 * 首先获取到set集合对象,然后才能进行添加元素; 所以先调用getXXX()方法获取对象,然后add
		 */
		// 客户关联联系人
		customer.getLinkMans().add(linkMan1);
		customer.getLinkMans().add(linkMan2);
		// 联系人关联客户
		linkMan1.setCustomer(customer);
		linkMan2.setCustomer(customer);
		// 执行操作
		session.save(linkMan1);
		session.save(linkMan2);
		session.save(customer);
		// 提交事务
		transaction.commit();
          //执行结果 /** * Hibernate: insert into linkman (lkm_name, lkm_gender, lkm_phone, * lkm_mobile, lkm_email, lkm_qq, lkm_position, lkm_cust_id) values (?, * ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into linkman (lkm_name, * lkm_gender, lkm_phone, lkm_mobile, lkm_email, lkm_qq, lkm_position, * lkm_cust_id) values (?, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into * customer (cust_name, cust_source, cust_industry, cust_level, * cust_phone, cust_mobile) values (?, ?, ?, ?, ?, ?) Hibernate: update * linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, lkm_mobile=?, * lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? where lkm_id=? * Hibernate: update linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, * lkm_mobile=?, lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? * where lkm_id=? Hibernate: update linkman set lkm_cust_id=? where * lkm_id=? Hibernate: update linkman set lkm_cust_id=? where lkm_id=? */ }

 级联操作:

指在主控方执行保存、更新和删除操作时,其关联(被控方)也执行相同操作。在映射文件中通过对cascade属性的设置来控制是否对关联对象采用级联操作,级联操作对各种关联关系都是有效的;

级联具有方向性:在保存一的一方级联多的一方和在多的一方可以级联一的一方;

在映射文件中配置cascade=“save-update”;

级联删除和级联保存、更新:谁是主控方,则可以在映射文件中配置cascade=“delete、save-update”,也可以同时配置;

级联删除:在set标签中配置cascade=“delete”或者在mony-to-one中配置cascade属性;

<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
			column="lkm_cust_id" cascade="save-update"  />

 或者

<set name="linkMans" cascade="delete,save-update" >
			<key column="lkm_cust_id" />
			<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
		</set>

 

防止SQL语句冗余:双向维护关系,持久态对象可以自动更新数据库,更新客户的时候会修改一次外键,更新联系人的时候会修改一次外键,所以会产生SQL语句冗余;

解决方案:一方放弃外键的维护,通常交给多的一方去维护,所以一的一方就需要放弃维护,即需要配置inverse=“true”;

<set name="linkMans" cascade="delete,save-update" inverse="true">
            <key column="lkm_cust_id" />
            <one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
        </set>

 

在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溪.源

你的鼓励将是我源源不断的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值