day70,JPA,多表操作,

搭建案例框架所需配置:

pom.xml 文件
<properties>
        <spring.version>4.2.4.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>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </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>

        <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>

        <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>4.2.4.RELEASE</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 -->

    </dependencies>

spring配置文件:

<?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">
    <!-- 1.dataSource 配置数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa331" />
        <property name="user" value="root" />
        <property name="password" value="123" />
    </bean>
    <!--工厂类对象-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--实体类的包扫描器-->
        <property name="packagesToScan" value="com.itheima.jpa.entity"/>
        <!--配置供应商适配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--是否向控制台输出sql语句-->
                <property name="showSql" value="true"/>
                <!--是否自动创建表
                    如果是true:相当于update,hibernate.hbm2ddl.auto属性配置成update
                    如果是false:相当于none
                -->
                <property name="generateDdl" value="false"/>
                <!--使用的数据库类型-->
                <property name="database" value="MYSQL"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
            	<!--update在现有表的基础上,进行修改,改为Create,就是jpa重新创建表-->
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
    <!--配置事务-->
    <!-- 3.事务配置-->
    <!-- 3.1JPA事务管理器  -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <!-- 3.2.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>
    <!-- 3.3.aop-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.itheima.jpa.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
    </aop:config>
    <!--dao的包扫描器-->
    <jpa:repositories base-package="com.itheima.jpa.dao"
                      transaction-manager-ref="transactionManager"
                      entity-manager-factory-ref="entityManagerFactory"/>
</beans>

一、表和表之间的关系
1、一对一的关系
A、B两张表,A表中的每条记录都对应B表的一条记录,反之亦然。
2、一对多关系
A、B两张表,A表中的每条记录都对应B表中的多条记录。B表中的多条对应A表中的一条记录。
3、多对多的关系
A、B两张表。A表中的每条记录对应B表中的多条,B表中的每条记录对应A表中的多条记录。
需要有一个中间表C记录多对多的关系。
————————————————————————————————
3、外键方案
使用客户表和客户扩展表。
配置关联关系:
1)在Customer实体类中添加一个属性CustomerExt类型
2)在属性上添加一个@OneToOne代表是一个一对一的关系
3)在属性上添加一个@JoinColumn
name:存储外键的字段的名称
referencedColumnName:对方表的主键字段的名称(可以不用配置)
测试:
1)创建一个Customer对象
2)创建一个CustomerExt对象
3)配置对象的关联关系。
4)把对象写入数据库。
插入数据应该开启事务。可以使用@Transactional注解开启事务。
无需在两个表中都添加外键。只需要在一个表中记录外键即可。
可以在一方放弃维护权:
删除@JoinColumn注解
在@OneToOne注解中添加mappedBy属性,值应该是对方实体类维护关联关系属性的名称。
@OneToOne(mappedBy = “ext”)
4、级联操作
需要在@OneToOne注解中添加一个属性cascade:
CascadeType.PERSIST:级联添加
CascadeType.MERGE:级联更新
CascadeType.REMOVE:级联删除
CascadeType.ALL:增删改都级联处理。
5、主键方案
使用方法:
不使用@JoinColumn注解
使用@PrimaryKeyJoinColumn注解,不需要配置属性。
双方都需要添加
——————————————————————————————
1对1案例:顾客实体类

//代表是一个jpa的顾客实体类
@Entity
//配置实体类和数据库中表的映射关系 name对应的表名
@Table(name = "cst_customer")
public class Customer {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    //配置属性和字段的映射关系
    @Column(name = "cust_id")
    private long custId;
    @Column(name = "cust_name")
    private String custName;
    @Column(name = "cust_source")
    private String custSource;
    @Column(name = "cust_industry")
    private String custIndustry;
    @Column(name = "cust_level")
    private String custLevel;
    @Column(name = "cust_address")
    private String custAddress;
    @Column(name = "cust_phone")
    private String custPhone;

    //表示是一对一的关联关系
//    需要在@OneToOne注解中添加一个属性cascade:
//    CascadeType.PERSIST:级联添加
//    CascadeType.MERGE:级联更新
//    CascadeType.REMOVE:级联删除
//    CascadeType.ALL:增删改都级联处理。
    @OneToOne(cascade = CascadeType.ALL)
    //连接的字段
    //name:当前表存储外键字段的名称
    //@JoinColumn(name = "extid", referencedColumnName = "ext_id")
    //使用主键关联(推荐,就是在1对1关联表中的对应属性添加 @PrimaryKeyJoinColumn 就行)
    @PrimaryKeyJoinColumn
    private CustomerExt ext;

	get,set省略。。。。

对应的顾客使用产品表

@Entity
@Table(name = "cst_customer_ext")
public class CustomerExt {
    @Id
    @Column(name = "ext_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long extId;
    private String memo;
    private String info;
	//对方实体类中对应关系的属性的名称
    @OneToOne/*(mappedBy = "ext")*/
    //@JoinColumn(name = "custid")
    
    @PrimaryKeyJoinColumn  //互有属性,都写这个主键注解(推荐)
    private Customer customer;
    get,set省略。。。。

在这里插入图片描述
测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class CustomerTest {

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private CustomerExtDao customerExtDao;


    @Test
    @Transactional
    @Commit
    public void oneToone(){
        //组装顾客用的产品对象。
        CustomerExt customerExt = new CustomerExt();
        //组装Customer顾客对象。
        Customer customer = new Customer();
        //--------不用设置主键,主键是自增长的----------------------------------
        customer.setCustName("小明");
        customer.setCustAddress("北京");
        //设置这个产品属于哪个顾客对象
        customer.setExt(customerExt);

        //设置这个产品属于哪个顾客对象
        customerExt.setCustomer(customer);
        customerExt.setMemo("产品1");

        //表间关系1对1,测试级联保存,和JPA创建表
        customerDao.save(customer);

    }
}

1对多表间关系:
2、关联关系的配置
一的一方:
1)添加一个属性记录多的一方的信息。应该是一个集合属性。
2)在属性上添加一个注解@OneToMany
3)使用@JoinColumn注解配置外键关系。
一定是多的一方记录外键,参照一的一方的主键。
多的一方:
1)在联系人实体类中添加一个Customer属性。
2)在属性上添加注解@ManyToOne
3)在属性上添加@JoinColumn注解
3、测试
1)每个实体类对应创建dao
2)在测试方法中,创建一个Customer2对象
3)创建LinkMan对象,可以创建多个。
4)配置客户和联系人之间的关系。
5)使用dao把数据写入数据库。
需要开启事务

只需要在一方维护关联关系即可,一方放弃维护。
一对多关系应该在一的一方访问维护交给多的一方来维护。
	删除@JoinColumn注解
	在@OneToMany注解中配置mappedBy属性

4、级联操作
应该只对主表进行操作即可,从表自动更新。
要求应该在@OneToMany注解中配置cascade属性
在这里插入图片描述

	/**一对多中的,多方实体类。
 * 联系人的实体类(数据模型)
 */
@Entity
@Table(name="cst_linkman")
public class LinkMan implements Serializable {
	@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(fetch = FetchType.LAZY)
	//custid,关联1方的主键属性名,cust_id,关联数据库表的主键列
	@JoinColumn(name = "custid", referencedColumnName = "cust_id")
	private Customer2 customer;
//代表是一个jpa的实体类,一对多中的1方实体类。
@Entity
//配置实体类和数据库中表的映射关系 name对应的表名
@Table(name = "cst_customer2")
public class Customer2 {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    //配置属性和字段的映射关系
    @Column(name = "cust_id")
    private long custId;
    @Column(name = "cust_name")
    private String custName;
    @Column(name = "cust_source")
    private String custSource;
    @Column(name = "cust_industry")
    private String custIndustry;
    @Column(name = "cust_level")
    private String custLevel;
    @Column(name = "cust_address")
    private String custAddress;
    @Column(name = "cust_phone")
    private String custPhone;
    //mappedBy = "customer",让多的一方中的customer 属性来维护一的一方,相关联
   // cascade = CascadeType.ALL 级联增删改,fetch = FetchType.LAZY,懒加载
    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    //JoinColumn配置关联的字段信息
    //name:外键字段的名称
    //referencedColumnName:参照一的一方的主键字段名称
    //@JoinColumn(name = "custid", referencedColumnName = "cust_id")
    private Set<LinkMan> linkMans = new HashSet<>();

五、多对多关联关系
1、场景
我们采用用户、角色的关系为例
需要第三张表记录关联关系。
2、配置关联关系
多对多的关联关系使用注解@ManyToMany配置。
1)在实体类中添加一个集合属性。
2)在属性上添加@ManyToMany注解。
3)使用@JoinTable注解配置关联关系。
@JoinTable注解就是中间表的定义。
name:中间表的名称
当前表和中间表的映射关系。
对方表和中间表的映射关系
************************************************************
在多对多关联关系中,只能一方维护关联关系,另外一方放弃维护权。
************************************************************

//相当于中间表的定义
   //name:中间表的表名
   @JoinTable(name = "sys_user_role", 
           joinColumns = @JoinColumn(
                   //中间表和当前表映射的字段的名称
                   name = "userid", 
                   //参照的当前表的主键字段
                   referencedColumnName = "user_id"),
           inverseJoinColumns = @JoinColumn(
                   name = "roleid",
                   referencedColumnName = "role_id"))

3、测试
对应每个实体类创建一个dao
创一个测试类
1)创建两个用户
2)创建两个角色
3)配置用户和角色之间的关联关系
4)把用户和角色写入数据库
需要开启事务
4、放弃维护权
删除@JoinTable注解(需要其中一方放弃维护权)
在@ManyToMany注解中添加mappedBy属性
5、配置级联操作
在@ManyToMany注解中配置cascade属性。
在这里插入图片描述
六、关联查询
1、使用导航的方式查询
使用“对象.属性”方式进行查询。
****对多的查询默认是延迟加载。
如果想修改默认行为:
在@OneToMany注解中添加一个属性fetch
FetchType.LAZY:延迟加载
FetchType.EAGER:及时加载
通过联系人查询客户:
****对一的查询默认是及时加载。
也可以配置成延迟加载。

对多的查询默认都是延迟加载,对一的查询默认都是即时加载,可以修改fetch属性修改默认行为。

2、使用Specification方式查询
1)需求
查询客户信息,根据联系人的手机号。

2)sql
		SELECT
			*
		FROM
			cst_customer2 a
		LEFT JOIN cst_linkman b ON a.cust_id = b.custid
		WHERE
			b.lkm_phone = '13344556678'

		需要使用Customer2Dao执行查询。需要继承JpaSpecificationExecutor接口。
		//使用root关联联系人表
        //参数1:Customer2实体类中关联的属性名称
        //参数2:连接方式
        Join<Object, Object> join = root.join("linkMans", JoinType.LEFT);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值