SpringBoot与数据访问

1. Tomcat.JDBC作为数据源

在项目中导入如下依赖:

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
</dependency>

创建配置文件:

spring:
  datasource:
    username: 用户
    password: 密码
    url: jdbc:mysql://你的数据库服务器IP/数据库名
    driver-class-name: com.mysql.jdbc.Driver

编写如下测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBoot06DataJdbcApplicationTests {

	@Autowired
	DataSource dataSource;

	@Test
	public void contextLoads() throws SQLException {
		System.out.println(dataSource.getClass());//org.apache.tomcat.jdbc.pool.DataSource
		Connection connection = dataSource.getConnection();
		System.out.println(connection);
		connection.close();
	}

}

输出org.apache.tomcat.jdbc.pool.DataSource可以看出,SpringBoot默认使用tomcat.jdbc作为数据源。

与数据源相关的配置都在DataSourceProperties类中可以看到。
在这里插入图片描述
在这里插入图片描述
其次我们深入看一下DataSourceInitializer的源码,可以发现两个很有趣的方法

	private void runSchemaScripts() {
		List<Resource> scripts = getScripts("spring.datasource.schema",
				this.properties.getSchema(), "schema");
		if (!scripts.isEmpty()) {
			String username = this.properties.getSchemaUsername();
			String password = this.properties.getSchemaPassword();
			runScripts(scripts, username, password);
			try {
				this.applicationContext
						.publishEvent(new DataSourceInitializedEvent(this.dataSource));
				// The listener might not be registered yet, so don't rely on it.
				if (!this.initialized) {
					runDataScripts();
					this.initialized = true;
				}
			}
			catch (IllegalStateException ex) {
				logger.warn("Could not send event to complete DataSource initialization ("
						+ ex.getMessage() + ")");
			}
		}
	}


	private void runDataScripts() {
		List<Resource> scripts = getScripts("spring.datasource.data",
				this.properties.getData(), "data");
		String username = this.properties.getDataUsername();
		String password = this.properties.getDataPassword();
		runScripts(scripts, username, password);
	}

作用:
​ 1)、runSchemaScripts();运行建表语句;

​ 2)、runDataScripts();运行插入数据的sql语句;
默认只需要将文件命名为:

schema-*.sql、data-*.sql
默认规则:schema.sql,schema-all.sql;
可以使用   
	schema:
      - classpath:department.sql
      指定位置

在这里插入图片描述
在这里插入图片描述
注意一点:不管建表还是插入数据,只执行一次就行了,在表和数据存在后,如果不删除此处的命令,便会又一次创建。

那我们到底改如何操纵数据库:SpringBoot自动配置了JdbcTemplate操作数据库。有关此内容我不再赘述,JdbcTemplate作为spring对jdbc的又一次封装,更为便捷。

2. 如何整合其他数据源(以Druid数据源为例)

首先我们探究DataSourceConfiguration的静态内部类Generic

@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
   @Bean
   public DataSource dataSource(DataSourceProperties properties) {
       //使用DataSourceBuilder创建数据源,利用反射创建响应type的数据源,并且绑定相关属性
      return properties.initializeDataSourceBuilder().build();
   }
}

在POM文件中引入数据源依赖

		<!--引入druid数据源-->
		<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.8</version>
		</dependency>

在这里插入图片描述
此时,我们在配置文件中已经说明数据源类型与数据源相关的配置,接下来我们只需配置数据源的监控即可

导入druid数据源
@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid(){
       return  new DruidDataSource();
    }

    //配置Druid的监控
    //1、配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();

        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        initParams.put("allow","");//默认就是允许所有访问
        initParams.put("deny","192.168.15.21");

        bean.setInitParameters(initParams);
        return bean;
    }


    //2、配置一个web监控的filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));

        return  bean;
    }
}

有关Druid的知识,大家可以去参考官方文档。

3. SpringBoot中如何使用Mybatis框架

首先肯定是导入依赖

<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>1.3.1</version>
</dependency>

使用步骤如下:
1.配置数据源(1和2小节已经说明)
2.数据库建表
3.创建JavaBean
4.注解版使用
我将我的项目结构展示如下
在这里插入图片描述

//指定这是一个操作数据库的mapper
@Mapper
public interface DepartmentMapper {

    @Select("select * from department where id=#{id}")
    public Department getDeptById(Integer id);

    @Delete("delete from department where id=#{id}")
    public int deleteDeptById(Integer id);

    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into department(departmentName) values(#{departmentName})")
    public int insertDept(Department department);

    @Update("update department set departmentName=#{departmentName} where id=#{id}")
    public int updateDept(Department department);
}

在mapper包下的接口中,我们使用注解已经完成了操作数据库的逻辑。注解不要遗漏注解。
我们也可以自定义MyBatis的配置规则,比如我们打开驼峰命名规则。

给容器中添加一个ConfigurationCustomizer

@org.springframework.context.annotation.Configuration
public class MyBatisConfig {
    @Bean
    public ConfigurationCustomizer configurationCustomizer(){
        return new ConfigurationCustomizer(){
            @Override
            public void customize(Configuration configuration) {
                configuration.setMapUnderscoreToCamelCase(true);
            }
        };
    }
}

如果mapper中的接口过于多,我们使用批量扫描注解

//使用MapperScan批量扫描所有的Mapper接口;
@MapperScan(value = "com.atguigu.springboot.mapper")
@SpringBootApplication
public class SpringBoot06DataMybatisApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBoot06DataMybatisApplication.class, args);
	}
}
  1. 配置文件版的使用

首先我先指出配置文件的映射

mybatis:
  config-location: classpath:mybatis/mybatis-config.xml 指定全局配置文件的位置
  mapper-locations: classpath:mybatis/mapper/*.xml  指定sql映射文件的位置

我的目录结构如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. SpringBoot整合SpringData JPA

4.1 SpringData JPA介绍

SpringData就是Spring提供了一个操作数据的框架。而SpringData JPA只是SpringData框架下的一个基于JPA标准操作数据的模块。
SpringData JPA:基于JPA的标准进行数据操作。简化操作持久层的代码。只需要编写接口就可以。

4.2 SpringBoot整合SpringData JPA

4.2.1 导入maven依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

4.2.2 编写配置文件

spring:
  datasource:
    url: jdbc:mysql://192.168.15.22/jpa
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
#  create:每次运行程序时,都会重新创建表,故而数据会丢失
#  create-drop:每次运行程序时会先创建表结构,然后待程序结束时清空表
#  upadte:每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
#  validate:运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错
#  none: 禁用DDL处理

#    控制台显示SQL
    show-sql: true

4.2.3 编写实体类

import javax.persistence.*;
//使用JPA注解配置映射关系
@Entity//告诉JPA这是一个实体类(和数据表映射的类)
@Table(name="t_users")//@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class Users {

	@Id	//主键id
	@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略
	@Column(name="id")//数据库字段名
	private Integer id;
	
	@Column(name="name")
	private String name;
	
	@Column(name="age")
	private Integer age;
	
	@Column(name="address")
	private String address;

	@ManyToOne(cascade = CascadeType.PERSIST)	//表示多方
	@JoinColumn(name ="role_id")	//维护一个外键,外键在Users一侧
	private Roles roles;

	public Roles getRoles() {
		return roles;
	}

	public void setRoles(Roles roles) {
		this.roles = roles;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public Integer getAge() {
		return age;
	}

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

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer("Users{");
		sb.append("id=").append(id);
		sb.append(", name='").append(name).append('\'');
		sb.append(", age=").append(age);
		sb.append(", address='").append(address).append('\'');
		sb.append(", roles=").append(roles);
		sb.append('}');
		return sb.toString();
	}
}

4.2.4 编写Dao接口

/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 *
 */
public interface UsersRepository extends JpaRepository<Users,Integer> {

}

4.2.5 测试

@RestController
public class UserController {

    @Autowired
    UserRepository userRepository;

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable("id") Integer id){
        User user = userRepository.findOne(id);
        return user;
    }

    @GetMapping("/user")
    public User insertUser(User user){
        User save = userRepository.save(user);
        return save;
    }

}

4.2.6 探究JPA提供的核心接口

  • Repository接口
  • CrudRepository接口
  • PagingAndSortingRepository接口
  • JpaRepository接口
  • JPASpecificationExecutor接口
1)Repository接口的使用
  • 提供了方法名称命名查询方式
  • 提供了基于@Query注解查询与更新
/**
 * Repository接口方法名称命名查询
 *
 */
public interface UsersRepositoryByName extends Repository<Users,Integer> {
    //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写)
    List<Users> findByName(String name);

    List<Users> findByNameAndAge(String name,Integer age);

    List<Users> findByNameLike(String name);

}
/**
	 * Repository
	 */
	@Test
	public void UsersRepositoryByName(){
		List<Users> list=this.usersRepositoryByName.findByName("张三");
		for (Users users:list){
			System.out.println(users);
		}
	}

	@Test
	public void findByNameAndAge(){
		List<Users> list=this.usersRepositoryByName.findByNameAndAge("张三",20);
		for (Users users:list){
			System.out.println(users);
		}
	}

	@Test
	public void findByNameLike() {
		List<Users> list = this.usersRepositoryByName.findByNameLike("张%");
		for (Users users : list) {
			System.out.println(users);
		}
	}
/**
 * 〈一句话功能简述〉<br> 
 *  Repository    @Query
 *
 * @author admin
 * @create 2019/5/22
 * @since 1.0.0
 */
public interface UsersRepositoryQueryAnnotation extends JpaRepository<Users,Integer> {
    @Query(value = "select * from t_user where name=?",nativeQuery = true)
    List<Users> queryByNameUseSQL(String name);

    @Query("update Users set name=? where id=?")
    @Modifying  //需要执行一个更新操作
    void updateUsersNameById(String name,Integer id);

}
public void testQueryByNameUseSQL() {
		List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseSQL("张三");
		for (Users users : list) {
			System.out.println(users);
		}
	}

	/**
	 * Repository--@Query测试
	 */
	@Test
	@Transactional //@Transactional与@Test 一起使用时 事务是自动回滚的。
	@Rollback(false) //取消自动回滚
	public void testUpdateUsersNameById() {
		this.usersRepositoryQueryAnnotation.updateUsersNameById("张三三", 1);
	}
2)CrudRepository接口的使用

CrudRepository接口,主要是完成一些增删改查的操作。注意:CrudRepository接口继承了Repository接口

public interface UsersRepositoryCrudRepository extends CrudRepository<Users,Integer> {
}
@Test
	public void testCrudRepositorySave() {
		Users users=new Users();
		users.setName("青衫");
		users.setAge(30);
		users.setAddress("湖南怀化");
		this.usersRepositoryCrudRepository.save(users);
	}

	@Test
	public void testCrudRepositoryUpdate() {
		Users users=new Users();
		users.setId(4);
		users.setName("青");
		users.setAge(18);
		users.setAddress("怀化");
		this.usersRepositoryCrudRepository.save(users);
	}

	@Test
	public void testCrudRepositoryFindOne() {

		Users users=this.usersRepositoryCrudRepository.findOne(4);
		System.out.println(users);
	}

	@Test
	public void testCrudRepositoryFindAll() {
		List<Users> list= (List<Users>) this.usersRepositoryCrudRepository.findAll();
		for (Users user:list){
			System.out.println(user);
		}
	}

	@Test
	public void testCrudRepositoryDeleteById() {
		this.usersRepositoryCrudRepository.delete(4);
		
	}
3)PagingAndSortingRepository接口的使用

该接口提供了分页与排序的操作,注意:该接口继承了CrudRepository接口

import com.bjsxt.pojo.Users;
import org.springframework.data.repository.PagingAndSortingRepository;

public interface UsersRepositoryPagingAndSorting extends PagingAndSortingRepository<Users,Integer> {

}
@Test
	public void testPagingAndSortingRepositorySort() {
		//Order	定义了排序规则
		Sort.Order order=new Sort.Order(Sort.Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort=new Sort(order);
		List<Users> list= (List<Users>) this.usersRepositoryPagingAndSorting.findAll(sort);
		for (Users users:list){
			System.out.println(users);
		}
	}

	@Test
	public void testPagingAndSortingRepositoryPaging() {
		//Pageable:封装了分页的参数,当前页,煤业显示的条数。注意:它的当前页是从0开始
		//PageRequest(page,size):page表示当前页,size表示每页显示多少条
		Pageable pageable=new PageRequest(1,2);
		Page<Users> page=this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("数据的总条数:"+page.getTotalElements());
		System.out.println("总页数:"+page.getTotalPages());
		List<Users> list=page.getContent();
		for (Users users:list){
			System.out.println(users);
		}
	}

	@Test
	public void testPagingAndSortingRepositorySortAndPaging() {
		Sort sort=new Sort(new Sort.Order(Sort.Direction.DESC,"id"));
		Pageable pageable=new PageRequest(0,2,sort);
		Page<Users> page=this.usersRepositoryPagingAndSorting.findAll(pageable);
		System.out.println("数据的总条数:"+page.getTotalElements());
		System.out.println("总页数:"+page.getTotalPages());
		List<Users> list=page.getContent();
		for (Users users:list){
			System.out.println(users);
		}
	}
4)JpaRepository接口

该接口继承了PagingAndSortingRepository。对继承的父接口中方法的返回值进行适配。

/**
 * 参数一 T :当前需要映射的实体
 * 参数二 ID :当前映射的实体中的OID的类型
 *
 */
public interface UsersRepository extends JpaRepository<Users,Integer> {

}
/**
	 * JpaRepository	排序测试
	 */
	@Test
	public void testJpaRepositorySort() {
		//Order	定义了排序规则
		Sort.Order order=new Sort.Order(Sort.Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort=new Sort(order);
		List<Users> list= this.usersRepository.findAll(sort);
		for (Users users:list){
			System.out.println(users);
		}
	}
5)JPASpecificationExecutor接口

该接口主要是提供了多条件查询的支持,并且可以在查询中添加排序与分页。注意JPASpecificationExecutor是单独存在的。完全独立

/**
 * 〈一句话功能简述〉<br> 
 *  JpaSpecificationExecutor
 *
 * @author admin
 * @create 2019/5/23
 * @since 1.0.0
 */
public interface UserRepositorySpecification extends JpaRepository<Users,Integer>,JpaSpecificationExecutor<Users> {
}
@Test
	public void testJpaSpecificationExecutor1() {
		/**
		 * Specification:用于封装查查询条件
		 */
		Specification<Users> spec=new Specification<Users>() {
			//Predicate:封装了单个查询条件

			/**
			 * @param root		对查询对象属性的封装
			 * @param criteriaQuery	封装了我们要执行的查询中的各个部分的信息,select from order
			 * @param criteriaBuilder	查询条件的构造器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
				//where name="张三"
				/**
				 * 参数一:查询的属性
				 * 参数二:条件的值
				 */
				Predicate predicate=criteriaBuilder.equal(root.get("name"),"张三");
				return predicate;
			}
		};
		List<Users> list=this.userRepositorySpecification.findAll(spec);
		for (Users users:list){
			System.out.println(users);
		}
	}

	/**
	 * JpaSpecificationExecutor		多条件查询方式一
	 */
	@Test
	public void testJpaSpecificationExecutor2() {
		/**
		 * Specification:用于封装查查询条件
		 */
		Specification<Users> spec=new Specification<Users>() {
			//Predicate:封装了单个查询条件

			/**
			 * @param root		对查询对象属性的封装
			 * @param criteriaQuery	封装了我们要执行的查询中的各个部分的信息,select from order
			 * @param criteriaBuilder	查询条件的构造器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
				//where name="张三" and age=20
				/**
				 * 参数一:查询的属性
				 * 参数二:条件的值
				 */
				List<Predicate> list=new ArrayList<>();
				list.add(criteriaBuilder.equal(root.get("name"),"张三"));
				list.add(criteriaBuilder.equal(root.get("age"),20));
				Predicate[] arr=new Predicate[list.size()];
				return criteriaBuilder.and(list.toArray(arr));
			}
		};
		List<Users> list=this.userRepositorySpecification.findAll(spec);
		for (Users users:list){
			System.out.println(users);
		}
	}
	
		Sort sort=new Sort(new Sort.Order(Sort.Direction.DESC,"id"));
		List<Users> list=this.userRepositorySpecification.findAll(spec,sort);
		for (Users users:list){
			System.out.println(users);
		}
	}

4.2.7 关联映射操作

1)一对多的关联关系

需求:角色与用户的一对多的关联关系
  角色:一方
  用户:多方

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

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author admin
 * @create 2019/5/23
 * @since 1.0.0
 */
@Entity
@Table(name = "t_roles")
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "role_id")
    private Integer roleId;
    @Column(name = "role_name")
    private String roleName;

    @OneToMany(mappedBy = "roles")
    private Set<Users> users=new HashSet<>();

    public Integer getRoleId() {
        return roleId;
    }

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

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

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

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


}
@Entity
@Table(name="t_users")
public class Users {

	@Id	//主键id
	@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略
	@Column(name="id")
	private Integer id;
	
	@Column(name="name")
	private String name;
	
	@Column(name="age")
	private Integer age;
	
	@Column(name="address")
	private String address;

	@ManyToOne(cascade = CascadeType.PERSIST)	//表示多方
	@JoinColumn(name ="role_id")	//维护一个外键,外键在Users一侧
	private Roles roles;

	public Roles getRoles() {
		return roles;
	}

	public void setRoles(Roles roles) {
		this.roles = roles;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer("Users{");
		sb.append("id=").append(id);
		sb.append(", name='").append(name).append('\'');
		sb.append(", age=").append(age);
		sb.append(", address='").append(address).append('\'');
		sb.append(", roles=").append(roles);
		sb.append('}');
		return sb.toString();
	}
}

2)多对多的关联关系

角色与菜单多对多关联关系
 菜单:多方
 角色:多方

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author admin
 * @create 2019/5/23
 * @since 1.0.0
 */
@Entity
@Table(name = "t_menus")
public class Menus {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "menus_id")
    private Integer menusId;
    @Column(name = "menus_name")
    private String menusName;
    @Column(name = "menus_url")
    private String menusUrl;
    @Column(name = "father_id")
    private Integer fatherId;

    @ManyToMany(mappedBy = "menus")
    private Set<Roles> roles=new HashSet<>();

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

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

    public Integer getMenusId() {
        return menusId;
    }

    public void setMenusId(Integer menusId) {
        this.menusId = menusId;
    }

    public String getMenusName() {
        return menusName;
    }

    public void setMenusName(String menusName) {
        this.menusName = menusName;
    }

    public String getMenusUrl() {
        return menusUrl;
    }

    public void setMenusUrl(String menusUrl) {
        this.menusUrl = menusUrl;
    }

    public Integer getFatherId() {
        return fatherId;
    }

    public void setFatherId(Integer fatherId) {
        this.fatherId = fatherId;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Menus{");
        sb.append("menusId=").append(menusId);
        sb.append(", menusName='").append(menusName).append('\'');
        sb.append(", menusUrl='").append(menusUrl).append('\'');
        sb.append(", fatherId=").append(fatherId);
        sb.append('}');
        return sb.toString();
    }
}

@Entity
@Table(name = "t_roles")
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "role_id")
    private Integer roleId;
    @Column(name = "role_name")
    private String roleName;

    @OneToMany(mappedBy = "roles")
    private Set<Users> users=new HashSet<>();

    @ManyToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
    //映射中间表  joinColumns:当前表中的主键关联中间表的外键
    @JoinTable(name = "t_roles_menus",joinColumns =@JoinColumn(name = "role_id"),inverseJoinColumns = @JoinColumn(name = "menu_id"))
    private Set<Menus> menus=new HashSet<>();

    public Set<Menus> getMenus() {
        return menus;
    }

    public void setMenus(Set<Menus> menus) {
        this.menus = menus;
    }

    public Integer getRoleId() {
        return roleId;
    }

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

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

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

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

public interface RolesRepository extends JpaRepository<Roles,Integer> {

}
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = App.class)
public class ManyToManyTest {

    @Autowired
    private RolesRepository rolesRepository;

    /**
     * 添加测试
     */
    @Test
    public void testSave(){
        //创建角色对象
        Roles roles=new Roles();
        roles.setRoleName("项目经理");
        //创建菜单对象
        Menus menus=new Menus();
        menus.setMenusName("xxxx管理系统");
        menus.setFatherId(0);

        Menus menus2=new Menus();
        menus2.setFatherId(1);
        menus2.setMenusName("项目管理");
        //关联
        roles.getMenus().add(menus);
        roles.getMenus().add(menus2);
        menus.getRoles().add(roles);
        menus2.getRoles().add(roles);
        //保存
        this.rolesRepository.save(roles);
    }

    /**
     * 查询操作
     */
    @Test
    public void testFind(){
        Roles roles=this.rolesRepository.findOne(2);
        System.out.println(roles.getRoleName());
        Set<Menus> menus=roles.getMenus();
        for (Menus menu:menus){
            System.out.println(menu);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值