springDataJpa联表查询之多对多

springDataJpa联表查询之多对多

场景模拟

  • 一个用户User可以有多个角色Role 一个角色可以有多个用户

分析

  • 用户表
  • 角色表
  • 用户角色中间表 userId,roleId两个字段都是外键引用

UserEntity

package cn.liyang.jpa.entity;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

/**
 * @author liyang
 * @date 2019/8/21 17:44
 * @description:
 */
@Entity
@Table(name = "sys_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long userId;
    @Column(name = "user_name")
    private String userName;
    @Column(name = "age")
    private Integer age;
    /*
    *一个用户可以有多个角色
    *  多对多配置
    * */
    //targetEntity代表要连接的表的字节码文件
    @ManyToMany (targetEntity = Role.class)
    //用户与角色形成的中间表
    @JoinTable(name = "sys_user_role",   //中间表的名字
            //当前对象在中间表中的外键配置name : 外键在中间表中的字段名字 referencedColumnName : 引用表的字段名字
            joinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")} ,
            //目标链表对象的外键配置
            inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")}
    )
    private Set<Role> roles = new HashSet<>();

    @Override
    public String toString () {
        return "User{" + "userId=" + userId + ", userName='" + userName + '\'' + ", age=" + age + ", roles=" + roles + '}';
    }

    public Long getUserId () {
        return userId;
    }

    public void setUserId (Long userId) {
        this.userId = userId;
    }

    public String getUserName () {
        return userName;
    }

    public void setUserName (String userName) {
        this.userName = userName;
    }

    public Integer getAge () {
        return age;
    }

    public void setAge (Integer age) {
        this.age = age;
    }

    public Set<Role> getRoles () {
        return roles;
    }

    public void setRoles (Set<Role> roles) {
        this.roles = roles;
    }
}

RoleEntity

package cn.liyang.jpa.entity;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

/**
 * @author liyang
 * @date 2019/8/21 17:31
 * @description:
 */
@Entity
@Table(name = "sye_role")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "role_id")
    private Long roleId;
    @Column(name = "role_name")
    private String name;

    public Set<User> getUsers () {
        return users;
    }

    public void setUsers (Set<User> users) {
        this.users = users;
    }

    //多对多表查询
    @ManyToMany(targetEntity = User.class)
    @JoinTable(name = "sys_user_role",
            joinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")},
            inverseJoinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")}
    )
    private Set<User> users = new HashSet<>();

    @Override
    public String toString () {
        return "Role{" + "roleId=" + roleId + ", name='" + name + '\'' + ", users=" + users + '}';
    }

    public Long getRoleId () {
        return roleId;
    }

    public void setRoleId (Long roleId) {
        this.roleId = roleId;
    }

    public String getName () {
        return name;
    }

    public void setName (String name) {
        this.name = name;
    }
}

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">
    <!--数据源-->
    <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/springdata"/>
        <property name="password" value="root"/>
        <property name="user" value="root"/>
    </bean>
    <!--entityManager实体工厂-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!--指定数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--配对应的实体类-->
        <property name="packagesToScan" value="cn.liyang.jpa.entity"/>
        <!--配置供应商的适配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true"/>
                <property name="generateDdl" value="false"/>
                <property name="database" value="MYSQL"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
    <!--事务管理 配置事务-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <tx:advice id="txAvice" 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>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* cn.liyang.jpa.service.*.*(..))"/>
        <aop:advisor advice-ref="txAvice" pointcut-ref="pointcut"/>
    </aop:config>
    <!--dao包扫描器-->
    <jpa:repositories base-package="cn.liyang.jpa.dao"
                      transaction-manager-ref="transactionManager"
                      entity-manager-factory-ref="entityManagerFactory"/>

</beans>

测试类ManyToMany

package cn.liyang.jpa;

import cn.liyang.jpa.dao.RoleDao;
import cn.liyang.jpa.dao.UserDao;
import cn.liyang.jpa.entity.Role;
import cn.liyang.jpa.entity.User;
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;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class ManyToMany {
    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;
    @Test
    @Transactional  //开启事务
    @Rollback(false)    //拒绝回滚
    public void testAdd(){//新建角色,新建用户同时添加
        User user = new User();
        user.setAge( 18 );
        user.setUserName( "liyang02" );
        Role role = new Role();
        role.setName( "程序员02" );
        user.getRoles().add( role );
        userDao.save( user );
        roleDao.save( role );
    }
    @Test
    @Transactional  //开启事务
    @Rollback(false)    //拒绝回滚
    public void testAdd02(){//查询用户,创建一个新的角色类型,并为该用户添加这个角色
        User one = userDao.findOne( 2L );
        Role role = new Role();
        role.setName( "产品经理" );
        one.getRoles().add( role );
        roleDao.save( role );
    }
    @Test
    @Transactional  //开启事务
    @Rollback(false)    //拒绝回滚
    public void testAdd03(){//查询一条已经存在的用户和一条角色,并为该用户赋予这个角色
        Role role = roleDao.findOne( 2L );
        User user = userDao.findOne( 1L );
        user.getRoles().add( role );
    }
    @Test
    @Transactional  //开启事务
    @Rollback(false)    //拒绝回滚
    public void testAdd04(){//新建一个用户,并为该用户添加多个角色
        Role role1 = roleDao.findOne( 1L );
        Role role2 = roleDao.findOne( 2L );
        Role role3 = roleDao.findOne( 3L );
        User user = new User();
        user.setUserName( "郑愁予" );
        user.getRoles().add( role1 );
        user.getRoles().add( role2 );
        user.getRoles().add( role3 );
        userDao.save( user );//这是新建的用户记得保存
    }
}

总结

  • 核心代码,在用户Entity中建立一个角色集合,在角色Entity中建立一个用户集合

    private Set<User> users = new HashSet<>();
    
    private Set<Role> roles = new HashSet<>();
    
  • 要创建一个中间表,表中添加外键,需要指明添加外键引用的是那一张表,哪一个字段,这些信息在集合属性注解中来完成

     /*
     *一个用户可以有多个角色
     *  多对多配置
     * */
     //targetEntity代表要连接的表的字节码文件
     @ManyToMany (targetEntity = Role.class)
     //用户与角色形成的中间表
     @JoinTable(name = "sys_user_role",   //中间表的名字
             //当前对象在中间表中的外键配置name : 外键在中间表中的字段名字 referencedColumnName : 引用表的字段名字
             joinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")} ,
             //目标链表对象的外键配置
             inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")}
     )
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值