1 表关系 一对一 一对多: 一的一方:主表。 多的一方:从表。 外键:需要再从表上新建一列作为外键,他的取值来源于主表的主键。 多对多: 中间表:中间表中最少应该由两个字段组成,这两个字段做为外键指向两张表的主键,又组成了联合主键。 讲师对学员:一对多关系。 实体类中的关系 包含关系:可以通过实体类中的包含关系描述表关系。 继承关系 分析步骤 1.明确表关系。 2.确定表关系(描述 外键|中间表)。 3.编写实体类,再实体类中描述表关系(包含关系)。 4.配置映射关系。 数据库中多表之间存在着三种关系,如图所示。 2 一对多:案例分析 一对多操作 案例:客户和联系人的案例(一对多关系)。 客户:一家公司。 联系人:这家公司的员工。 一个客户可以具有多个联系人。 一个联系人从属于一家公司。 分析步骤 1.明确表关系 一对多关系 2.确定表关系(描述 外键|中间表) 主表:客户表 从表:联系人表 再从表上添加外键 3.编写实体类,再实体类中描述表关系(包含关系) 客户:再客户的实体类中包含一个联系人的集合 联系人:在联系人的实体类中包含一个客户的对象 4.配置映射关系 1 使用jpa注解配置一对多映射关系 3 一对一的测试环境搭建 本案需要的创建数据库代码如下:
CREATE DATABASE jpa; USE jpa; -- 使用jpa数据库 -- 查看数据库的编码方式 SHOW CREATE TABLE cst_customer; -- 修改数据库编码信息 ALTER DATABASE jpa DEFAULT CHARACTER SET utf8;1.打开IDEA工具如图所示,点击Create New Project。 2.选择Maven工程和JDK的版本,并点击Next。如图所示: 3.填写相应的项目名称和保存的地址,如图所示:点击Finish。 4.导入相应的依赖jar包的代码如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.txw</groupId> <artifactId>jpa-day03_onetomany</artifactId> <version>1.0-SNAPSHOT</version> <!--打包的方式--> <packaging>jar</packaging> <!--锁定版本号--> <properties> <spring.version>5.0.2.RELEASE</spring.version> <hibernate.version>5.0.7.Final</hibernate.version> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> <c3p0.version>0.9.1.2</c3p0.version> <mysql.version>5.1.6</mysql.version> </properties> <dependencies> <!-- junit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring beg --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!-- spring对orm框架的支持包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <!-- spring end --> <!-- hibernate beg --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.1.Final</version> </dependency> <!-- hibernate end --> <!-- c3p0 beg --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency> <!-- c3p0 end --> <!-- log end --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- log end --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- spring data jpa 的坐标--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.9.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- el beg 使用spring data jpa 必须引入 --> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>2.2.4</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency> <!-- el end --> <!--导入lombok依赖jar包--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> </dependencies> </project>5.编写客户的实体类代码如下:
package com.txw.domain; import lombok.Data; import lombok.ToString; import javax.persistence.*; import java.util.HashSet; import java.util.Set; /** * 1.实体类和表的映射关系 * @Eitity * @Table * 2.类中属性和表中字段的映射关系 * @Id * @GeneratedValue * @Column * @author:Adair */ @Entity @Table(name="cst_customer") @Data // 自动生成set和get方法 @ToString // 重写toString方法 @SuppressWarnings("all") // 注解警告信息 public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="cust_id") private Long custId; // 客户的主键 @Column(name="cust_address") private String custAddress; // 客户地址 @Column(name="cust_industry") private String custIndustry; // 客户所属行业 @Column(name="cust_level") private String custLevel; // 客户级别 @Column(name="cust_name") private String custName; // 客户名称 @Column(name="cust_phone") private String custPhone; // 客户的联系方式 @Column(name="cust_source") private String custSource; // 客户来源 // 配置客户和联系人之间的关系(一对多关系) /** * 使用注解的形式配置多表关系 * 1.声明关系 * @OneToMany : 配置一对多关系 * targetEntity :对方对象的字节码对象 * 2.配置外键(中间表) * @JoinColumn : 配置外键 * name:外键字段名称 * referencedColumnName:参照的主表的主键字段名称 * * * 在客户实体类上(一的一方)添加了外键了配置,所以对于客户而言,也具备了维护外键的作用 */ @OneToMany(targetEntity = LinkMan.class) @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id") private Set<LinkMan> linkMans = new HashSet<>(); }6.编写客户的持久层接口的代码如下:
package com.txw.dao; import com.txw.domain.Customer; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; /** * 符合SpringDataJpa的dao层接口规范 * JpaRepository<操作的实体类类型,实体类中主键属性的类型> * * 封装了基本CRUD操作 * JpaSpecificationExecutor<操作的实体类类型> * * 封装了复杂查询(分页) * @author:Adair */ @SuppressWarnings("all") // 注解警告信息 public interface CustomerDao extends JpaRepository<Customer,Long> ,JpaSpecificationExecutor<Customer> { }7.在resources目录下创建applicationContext.xml的代码如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!--spring 和 spring data jpa的配置--> <!-- 1.创建entityManagerFactory对象交给spring容器管理--> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <!--配置的扫描的包(实体类所在的包) --> <property name="packagesToScan" value="com.txw.domain" /> <!-- jpa的实现厂家 --> <property name="persistenceProvider"> <bean class="org.hibernate.jpa.HibernatePersistenceProvider"/> </property> <!--jpa的供应商适配器 --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!--配置是否自动创建数据库表 --> <property name="generateDdl" value="false" /> <!--指定数据库类型 --> <property name="database" value="MYSQL" /> <!--数据库方言:支持的特有语法 --> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> <!--是否显示sql --> <property name="showSql" value="true" /> </bean> </property> <!--jpa的方言 :高级的特性 --> <property name="jpaDialect" > <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> </property> <!--注入jpa的配置信息 加载jpa的基本配置信息和jpa实现方式(hibernate)的配置信息 hibernate.hbm2ddl.auto : 自动创建数据库表 create : 每次都会重新创建数据库表 update:有表不会重新创建,没有表会重新创建表 --> <property name="jpaProperties" > <props> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> </bean> <!--2.创建数据库连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="root"></property> <property name="password" value="123456"></property> <property name="jdbcUrl" value="jdbc:mysql:///jpa?characterEncoding=utf-8" ></property> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> </bean> <!--3.整合spring dataJpa--> <jpa:repositories base-package="com.txw.dao" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory" ></jpa:repositories> <!--4.配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"></property> </bean> <!-- 4.txAdvice--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 5.aop--> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.txw.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config> <!--5.声明式事务 --> <!-- 6. 配置包扫描--> <context:component-scan base-package="com.txw" ></context:component-scan> </beans>8.编写联系人实体类的代码如下:
package com.txw.domain; import lombok.Data; import lombok.ToString; import javax.persistence.*; /** * 联系人的实体类 * @author Adair */ @Entity @Table(name = "cst_linkman") @Data // 自动生成set和get方法 @ToString // 重写toString方法 @SuppressWarnings("all") // 注解警告信息 public class LinkMan { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "lkm_id") private Long lkmId; // 联系人编号(主键) @Column(name = "lkm_name") private String lkmName; // 联系人姓名 @Column(name = "lkm_gender") private String lkmGender; // 联系人性别 @Column(name = "lkm_phone") private String lkmPhone; // 联系人办公电话 @Column(name = "lkm_mobile") private String lkmMobile; // 联系人手机 @Column(name = "lkm_email") private String lkmEmail; // 联系人邮箱 @Column(name = "lkm_position") private String lkmPosition; // 联系人职位 @Column(name = "lkm_memo") private String lkmMemo; // 联系人备注 /** * 配置联系人到客户的多对一关系 * 使用注解的形式配置多对一关系 * 1.配置表关系 * @ManyToOne : 配置多对一关系 * targetEntity:对方的实体类字节码 * 2.配置外键(中间表) * 配置外键的过程,配置到了多的一方,就会在多的一方维护外键 */ @ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY) @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id") private Customer customer; }9.编写联系人的持久层代码如下:
package com.txw.dao; import com.txw.domain.LinkMan; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; /** *符合SpringDataJpa的dao层接口规范 * JpaRepository<操作的实体类类型,实体类中主键属性的类型> * * 封装了基本CRUD操作 * JpaSpecificationExecutor<操作的实体类类型> * * 封装了复杂查询(分页) * @author: Adair */ @SuppressWarnings("all") // 注解警告信息 public interface LinkManDao extends JpaRepository<LinkMan,Long >,JpaSpecificationExecutor<LinkMan> { }10.编写测试保存代码如下:
package com.txw.test; import com.txw.dao.CustomerDao; import com.txw.dao.LinkManDao; import com.txw.domain.Customer; import com.txw.domain.LinkMan; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * 一对多测试 * @author:Adair */ @SuppressWarnings("all") // 注解警告信息 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class OneToManyTest { // 声明CustomerDao业务对象 @Autowired private CustomerDao customerDao; // 声明LinkManDao业务对象 @Autowired private LinkManDao linkManDao; /** * 保存一个客户,保存一个联系人 * 效果:客户和联系人作为独立的数据保存到数据库中 * 联系人的外键为空 * 原因? * 实体类中没有配置关系 */ @Test @Transactional //配置事务 @Rollback(false) //不自动回滚 public void testAdd() { //创建一个客户,创建一个联系人 Customer customer = new Customer(); customer.setCustName("学无止路"); customer.setCustSource("微信公众号"); customer.setCustIndustry("笔记"); customer.setCustLevel("VIP"); customer.setCustAddress("贵州省六盘水市"); customer.setCustPhone("1578533828*"); LinkMan linkMan = new LinkMan(); linkMan.setLkmName("Adair"); linkMan.setLkmGender("男"); linkMan.setLkmMobile("0858-1578533"); linkMan.setLkmPhone("1578533828*"); linkMan.setLkmEmail("1578533828@qq.com"); linkMan.setLkmPosition("行政人员"); linkMan.setLkmMemo("学习委员"); /** * 配置了客户到联系人的关系 * 从客户的角度上:发送两条insert语句,发送一条更新语句更新数据库(更新外键) * 由于我们配置了客户到联系人的关系:客户可以对外键进行维护 */ customer.getLinkMans().add(linkMan); customerDao.save(customer); linkManDao.save(linkMan); } }运行结果如图所示: 使用SELECT * FROM cst_customer; 运行如图所示: 使用SELECT * FROM cst_linkman; 运行如图所示: 联系人和客户关系如图所示: 3 放弃外键维护权 1.修改applicationContext.xml的代码如图所示: 2.编写配置联系人到客户的关系(多对一)的代码如下:
package com.txw.test; import com.txw.dao.CustomerDao; import com.txw.dao.LinkManDao; import com.txw.domain.Customer; import com.txw.domain.LinkMan; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * 对对一测试 * @author:Adair */ @SuppressWarnings("all") // 注解警告信息 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class OneToManyTest { // 声明CustomerDao业务对象 @Autowired private CustomerDao customerDao; // 声明LinkManDao业务对象 @Autowired private LinkManDao linkManDao; /** * 多对一 */ @Test @Transactional //配置事务 @Rollback(false) //不自动回滚 public void testAdd1() { //创建一个客户,创建一个联系人 Customer customer = new Customer(); customer.setCustName("学无止路"); customer.setCustSource("微信公众号"); customer.setCustIndustry("笔记"); customer.setCustLevel("VIP"); customer.setCustAddress("贵州省六盘水市"); customer.setCustPhone("1578533828*"); LinkMan linkMan = new LinkMan(); linkMan.setLkmName("Adair"); linkMan.setLkmGender("男"); linkMan.setLkmMobile("0858-1578533"); linkMan.setLkmPhone("1578533828*"); linkMan.setLkmEmail("1578533828@qq.com"); linkMan.setLkmPosition("行政人员"); linkMan.setLkmMemo("学习委员"); /** * 配置联系人到客户的关系(多对一) * 只发送了两条insert语句 * 由于配置了联系人到客户的映射关系(多对一) * */ linkMan.setCustomer(customer); customerDao.save(customer); linkManDao.save(linkMan); } }运行结果如图所示: 使用SELECT * FROM cst_linkman;运行如图所示: 3.修改客户实体类的放弃外键维护权的代码如下:
package com.txw.domain; import lombok.Data; import lombok.ToString; import javax.persistence.*; import java.util.HashSet; import java.util.Set; /** * 1.实体类和表的映射关系 * @Eitity * @Table * 2.类中属性和表中字段的映射关系 * @Id * @GeneratedValue * @Column * @author:Adair */ @Entity @Table(name="cst_customer") @Data // 自动生成set和get方法 @ToString // 重写toString方法 @SuppressWarnings("all") // 注解警告信息 public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="cust_id") private Long custId; // 客户的主键 @Column(name="cust_address") private String custAddress; // 客户地址 @Column(name="cust_industry") private String custIndustry; // 客户所属行业 @Column(name="cust_level") private String custLevel; // 客户级别 @Column(name="cust_name") private String custName; // 客户名称 @Column(name="cust_phone") private String custPhone; // 客户的联系方式 @Column(name="cust_source") private String custSource; // 客户来源 // 配置客户和联系人之间的关系(一对多关系) /** * 放弃外键维护权 * mappedBy:对方配置关系的属性名称\ * cascade : 配置级联(可以配置到设置多表的映射关系的注解上) * CascadeType.all : 所有 * MERGE :更新 * PERSIST :保存 * REMOVE :删除 * fetch : 配置关联对象的加载方式 * EAGER :立即加载 * LAZY :延迟加载 */ @OneToMany(mappedBy = "customer") private Set<LinkMan> linkMans = new HashSet<>(); }4.测试放弃外键维护权的代码如下:
package com.txw.test; import com.txw.dao.CustomerDao; import com.txw.dao.LinkManDao; import com.txw.domain.Customer; import com.txw.domain.LinkMan; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * 对对一测试 * @author:Adair */ @SuppressWarnings("all") // 注解警告信息 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class OneToManyTest { // 声明CustomerDao业务对象 @Autowired private CustomerDao customerDao; // 声明LinkManDao业务对象 @Autowired private LinkManDao linkManDao; /** * 会有一条多余的update语句 * 由于一的一方可以维护外键:会发送update语句 * 解决此问题:只需要在一的一方放弃维护权即可 */ @Test @Transactional // 配置事务 @Rollback(false) //不自动回滚 public void testAdd3() { //创建一个客户,创建一个联系人 Customer customer = new Customer(); customer.setCustName("学无止路"); customer.setCustSource("微信公众号"); customer.setCustIndustry("笔记"); customer.setCustLevel("VIP"); customer.setCustAddress("贵州省六盘水市"); customer.setCustPhone("1578533828*"); LinkMan linkMan = new LinkMan(); linkMan.setLkmName("Adair"); linkMan.setLkmGender("男"); linkMan.setLkmMobile("0858-1578533"); linkMan.setLkmPhone("1578533828*"); linkMan.setLkmEmail("1578533828@qq.com"); linkMan.setLkmPosition("行政人员"); linkMan.setLkmMemo("学习委员"); /** *由于配置了多的一方到一的一方的关联关系(当保存的时候,就已经对外键赋值) *由于配置了一的一方到多的一方的关联关系(发送一条update语句) */ // linkMan.setCustomer(customer); customer.getLinkMans().add(linkMan); customerDao.save(customer); linkManDao.save(linkMan); } }运行结果如图所示: 数据库的数据如图所示:外键是为null,不建议使用放弃外键维护权。 使用SELECT * FROM cst_customer;查询结果如图所示: 4 删除的说明和级联的引入 删除操作的说明如下: 删除从表数据:可以随时任意删除。 删除主表数据: 有从表数据。 1、在默认情况下,它会把外键字段置为null,然后删除主表数据。如果在数据库的表 结构上,外键字段有非空约束,默认情况就会报错了。 2、如果配置了放弃维护关联关系的权利,则不能删除(与外键字段是否允许为null, 没有关系)因为在删除时,它根本不会去更新从表的外键字段了。 3、如果还想删除,使用级联删除引用。 没有从表数据引用:随便删。 在实际开发中,级联删除请慎用!(在一对多的情况下)。 级联: 操作一个对象的同时操作他的关联对象。 级联操作: 1.需要区分操作主体。 2.需要在操作主体的实体类上,添加级联属性(需要添加到多表映射关系的注解上)。 3.cascade(配置级联)。 级联添加, 案例:当我保存一个客户的同时保存联系人。 修改客户的实体类代码如下:
package com.txw.domain; import lombok.Data; import lombok.ToString; import javax.persistence.*; import java.util.HashSet; import java.util.Set; /** * 1.实体类和表的映射关系 * @Eitity * @Table * 2.类中属性和表中字段的映射关系 * @Id * @GeneratedValue * @Column * @author:Adair */ @Entity @Table(name="cst_customer") @Data // 自动生成set和get方法 @ToString // 重写toString方法 @SuppressWarnings("all") // 注解警告信息 public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="cust_id") private Long custId; // 客户的主键 @Column(name="cust_address") private String custAddress; // 客户地址 @Column(name="cust_industry") private String custIndustry; // 客户所属行业 @Column(name="cust_level") private String custLevel; // 客户级别 @Column(name="cust_name") private String custName; // 客户名称 @Column(name="cust_phone") private String custPhone; // 客户的联系方式 @Column(name="cust_source") private String custSource; // 客户来源 // 配置客户和联系人之间的关系(一对多关系) /** * 放弃外键维护权 * mappedBy:对方配置关系的属性名称 * cascade : 配置级联(可以配置到设置多表的映射关系的注解上) * CascadeType.all : 所有 * MERGE :更新 * PERSIST :保存 * REMOVE :删除 * fetch : 配置关联对象的加载方式 * EAGER :立即加载 * LAZY :延迟加载 */ @OneToMany(mappedBy = "customer",cascade = CascadeType.ALL) private Set<LinkMan> linkMans = new HashSet<>(); }测试代码如下:
package com.txw.test; import com.txw.dao.CustomerDao; import com.txw.dao.LinkManDao; import com.txw.domain.Customer; import com.txw.domain.LinkMan; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * 对对一测试 * @author:Adair */ @SuppressWarnings("all") // 注解警告信息 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class OneToManyTest { // 声明CustomerDao业务对象 @Autowired private CustomerDao customerDao; // 声明LinkManDao业务对象 @Autowired private LinkManDao linkManDao; /** * 级联添加:保存一个客户的同时,保存客户的所有联系人 * 需要在操作主体的实体类上,配置casacde属性 */ @Test @Transactional // 配置事务 @Rollback(false) //不自动回滚 public void testCascadeAdd() { //创建一个客户,创建一个联系人 Customer customer = new Customer(); customer.setCustName("学无止路"); customer.setCustSource("微信公众号"); customer.setCustIndustry("笔记"); customer.setCustLevel("VIP"); customer.setCustAddress("贵州省六盘水市"); customer.setCustPhone("1578533828*"); LinkMan linkMan = new LinkMan(); linkMan.setLkmName("Adair"); linkMan.setLkmGender("男"); linkMan.setLkmMobile("0858-1578533"); linkMan.setLkmPhone("1578533828*"); linkMan.setLkmEmail("1578533828@qq.com"); linkMan.setLkmPosition("行政人员"); linkMan.setLkmMemo("学习委员"); customer.getLinkMans().add(linkMan); customerDao.save(customer); } }运行结果如图所示: 数据库查询结果如图所示: 级联删除 案例:当我删除一个客户的同时删除此客户的所有联系人。 测试代码如下:
package com.txw.test; import com.txw.dao.CustomerDao; import com.txw.dao.LinkManDao; import com.txw.domain.Customer; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * 对对一测试 * @author:Adair */ @SuppressWarnings("all") // 注解警告信息 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class OneToManyTest { // 声明CustomerDao业务对象 @Autowired private CustomerDao customerDao; // 声明LinkManDao业务对象 @Autowired private LinkManDao linkManDao; /** * 级联删除: * 删除1号客户的同时,删除1号客户的所有联系人 */ @Test @Transactional //配置事务 @Rollback(false) //不自动回滚 public void testCascadeRemove() { // 1.查询1号客户 Customer customer = customerDao.findOne(1l); // 2.删除1号客户 customerDao.delete(customer); } }运行之前的数据库结果如图所示: 运行结果如图所示: 运行之后数据库查询结果如图所示: