【Java WEB】MyBatis详解

家电修理 2023-07-16 19:16www.caominkang.com电器维修

个人主页Hello Code.
本文专栏《Java WEB从入门到实战》
Java WEB完整内容请点击前往Java WEB从入门到实战 查看
如有问题,欢迎指正,一起学习~~


文章目录

快速入门

MyBatis介绍入门程序 相关API映射配置文件

查询功能新增功能修改功能删除功能 核心配置文件

数据库连接配置文件引用起别名 Dao层的实现

传统方式接口代理方式 动态sql

if标签foreach标签SQL 片段的抽取 分页插件多表操作

一对一一对多多对多 注解开发

查询操作新增操作 注解多表操作构建SQL

查询操作新增操作修改操作删除操作


快速入门

框架是一款半成品软件,我们可以基于这个半成品软件继续开发,来完成我们的个性化需求

ORM(Object Relational Mapping)对象关系映射
指的是持久化数据和实体对象的映射模式,为了解决面向对象与关系型数据库存在的互不匹配的现象的技术 MyBatis介绍

原始 JDBC 的操作问题分析

    频繁创建和销毁数据库的连接会造成系统资源浪费从而影响系统性能sql 语句在代码中硬编码,如果要修改sql语句,就需要修改 java 代码,造成代码不易维护查询操作时,需要手动将结果集中的数据封装到实体对象中增删改查操作需要参数时,需要手动将实体对象的数据设置到sql 语句的占位符
原始 JDBC 的操作问题解决方案
    使用数据库连接池初始化连接资源将sql 语句抽取到配置文件中使用反射、内省等底层操作技术,将实体与表进行属性与字段的自动映射
MyBatis 是一个优秀的基于Java的持久层框架,它内部封装了 JDBC,使开发者只需要关注 SQL 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建执行者等复杂的操作MyBatis 通过xml 或注解的方式将要执行的各种 Statement 配置起来,并通过Java 对象和Statement 中 SQL 的动态参数进行映射生成最终要执行的SQL语句 MyBatis 框架执行完SQL 并将结果映射为 Java对象并返回。采用 ORM 思想解决了实体和数据库映射的问题,对 JDBC 进行了封装,屏蔽了 JDBC API 底层访问细节,使我们不用与 JDBC API 打交道,就可以完成对数据库的持久化操作MyBatis官网http://.mybatis. 入门程序

    数据库数据准备

    导入 jar 包

    在src 下创建映射配置文件

    
    
    
     
      SELECT  FROM student
     
    
    

    在 src 下创建核心配置文件

    
    
    
    
     
      
       
       
        
        
        
        
       
      
     
     
     
      
     
    
    

    编写测试类完成相关API 的使用

    运行测试查看结果

package mybatis.study.dao;

import mybatis.study.bean.Student;
import .apache.ibatis.io.Resources;
import .apache.ibatis.session.SqlSession;
import .apache.ibatis.session.SqlSessionFactory;
import .apache.ibatis.session.SqlSessionFactoryBuilder;
import .junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class StudentTest01 {
 
 @Test
 public void selectAll() thros IOException {
  // 1.加载核心配置文件
  InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

  // 2. 获取SqlSession工厂对象
  SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);

  // 3.通过SqlSession工厂对象获取SqlSession对象
  SqlSession sqlSession = sqlSessionFactory.openSession();

  // 4.执行映射配置文件中的sql语句,并接收结果
  List list = sqlSession.selectList("StudentMapper.selectAll");

  // 5.处理结果
  for(Student stu : list){
   System.out.println(stu);
  }

  // 6.释放资源
  sqlSession.close();
  is.close();
 }
}

相关API

Resources

.apache.ibaties.io.Resources加载资源的工具类核心方法 返回值方法名说明InputStreamgetResourcesAsStream(String fileName)通过类加载器返回指定资源的字节输入流

除了使用这个工具类的方法,还可以使用类名.class.getClassLoader().getResourceAsStream(配置文件名.xml)获取到字节输入流对象

SqlSessionFactoryBuilder

.apache.ibaties.session.SqlSessionFactoryBuilder获取SqlSessionFactory 工厂对象的功能类核心方法 返回值方法名说明SqlSessionFactorybuild(InputStream is)通过指定资源字节输入流获取SqlSession 工厂对象

SqlSessionFactory

.apache.ibaties.srssion.SqlSessionFactory获取SqlSession 构建者对象的工厂接口核心方法 返回值方法名说明SqlSessionopenSession()获取SqlSession 构建者对象,并开启手动提交事务SqlSessionopenSession(boolean autoCommit)获取SqlSession构建者对象,如果参数为true,则开启自动提交事务

SqlSession

.apache.ibaties.session.SqlSession构建者对象接口。用于执行SQL、管理事务、接口代理核心方法 返回值方法名说明ListselectList(String statement,Object paramter)执行查询语句,返回List集合TselectOne(String statement,Object paramter)执行查询语句,返回一个结果对象intinsert(String statement,Object paramter)执行新增语句,返回影响行数intupdate(String statement,Object paramter)执行修改语句,返回影响行数intdelete(String statement,Object paramter)执行删除语句,返回影响行数voidmit()提交事务voidrollback()回滚事务TgetMapper(Classcls)获取指定接口的代理实现类对象voidclose()释放资源


映射配置文件

映射配置文件包含了数据和对象之间的映射关系以及要执行的SQL语句






 
 
  SELECT  FROM student
 
 查询功能标签属性
id唯一标识
parameterType指定参数映射的对象类型
resultType指定结果映射的对象类型SQL 获取参数
#{属性名}

注意属性名要和对象中的成员变量名称一致,才能获取到正确的值

新增功能

	INSERT INTO student VALUES (#{id},#{name},#{age})

@Test
public void insert() thros IOException {
 InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
 SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
 SqlSession sqlSession = sqlSessionFactory.openSession(true);
 Student stu = ne Student(7,"老八",28);
 int result = sqlSession.insert("StudentMapper.insert", stu);
 // 如果没有开启自动提交事务,对于增删改,在执行完SQL后还需要提交事务
 // sqlSession.mit();
 System.out.println(result);
 is.close();
 sqlSession.close();
}

新增功能标签属性
id唯一标识,配合名称空间使用
parameterType指定参数映射的对象类型
resultType指定结果映射的对象类型

对于增删改操作,返回的的结果都是int类型的影响行数,故resultType可以省略不写

SQL获取参数
#{属性名}

注意属性名要和对象中的成员变量名称一致,才能获取到正确的值

修改功能

	UPDATE student SET name = #{name},age = #{age} WHERe id = #{id}

@Test
public void update() thros IOException {
 InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
 SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
 SqlSession sqlSession = sqlSessionFactory.openSession();
 Student stu = ne Student(6,"周七七",37);
 int result = sqlSession.insert("StudentMapper.update", stu);
 // 如果没有开启自动提交事务,对于增删改,在执行完SQL后还需要提交事务
 sqlSession.mit();
 System.out.println(result);
 is.close();
 sqlSession.close();
}

修改功能标签属性
id唯一标识,配合名称空间使用
parameterType指定参数映射的对象类型
resultType指定结果映射的对象类型SQL 获取参数
#{属性名} 删除功能


	DELETE FROM student WHERe id = #{id}

@Test
public void delete() thros IOException {
 InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
 SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
 SqlSession sqlSession = sqlSessionFactory.openSession();
 int result = sqlSession.delete("StudentMapper.delete", 7);
 System.out.println(result);
 // 提交事务
 sqlSession.mit();
 sqlSession.close();
 is.close();
}

删除功能标签属性
id唯一标识,配合名称空间使用
parameterType指定参数映射的对象类型
resultType指定结果映射的对象类型SQL 获取参数
#{属性名}


核心配置文件

核心配置文件包含了MyBatis 最核心的设置和属性信息。如数据库的连接、事务、连接池信息等







 
 
  
  
   
   
   
   
    
    
    
    
    
   
  
 
 
 
  
  
 

数据库连接配置文件引用

为了方便修改,可以将核心配置文件中的数据库连接信息抽取出来jdbc.properties

driver=.mysql.jdbc.Driver
url=jdbc:mysql://192.168.23.129
username=root
passord=密码
使用该标签可以引入数据库连接配置文件属性
resource数据库连接配置文件路径获取数据库连接参数
${键名}




 
 
 
  
   
   
    
    
    
    
    
   
  
 
 
  
 

起别名

为全类名起别名的父标签为全类名起别名的子标签属性
type指定全类名
alias指定别名为指定包下所有的类起别名的子标签(别名就是类名)


	
 

在核心配置文件中起别名后,就可以简化映射配置文件中的全类名

MyBatis自带的一些别名

别名数据类型stringjava.lang.Stringlongjava.lang.Longintjava.lang.Integerdoublejava.lang.Doublebooleanjava.lang.Boolean……
Dao层的实现 传统方式

分层思想控制层(controller)、业务层(service)、持久层(dao)调用流程
控制层 --> 业务层 --> 持久层 --> DB

在MyBatis中,持久层叫mapper

package mybatis.study.mapper;

import mybatis.study.bean.Student;

import java.util.List;

public interface StudentMapper {
 // 查询全部
 public abstract List selectAll();

 // 根据id查询
 public abstract Student selectById(Integer id);

 // 新增数据
 public abstract Integer insert(Student stu);

 // 修改数据
 public abstract Integer update(Student stu);

 // 删除数据
 public abstract Integer delete(Integer id);
}
package mybatis.study.mapper.impl;

import mybatis.study.bean.Student;
import mybatis.study.mapper.StudentMapper;
import .apache.ibatis.io.Resources;
import .apache.ibatis.session.SqlSession;
import .apache.ibatis.session.SqlSessionFactory;
import .apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class StudentMapperImpl implements StudentMapper {
 @Override
 public List selectAll() {
  InputStream is = null;
  SqlSession sqlSession = null;
  List list = null;
  try{
   is = Resources.getResourceAsStream("MyBatisConfig.xml");
   SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
   sqlSession = sqlSessionFactory.openSession(true);
   list = sqlSession.selectList("StudentMapper.selectAll");
  }catch (Exception e){
   e.printStackTrace();
  }finally {
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if(sqlSession != null){
    sqlSession.close();
   }
  }
  return list;
 }

 @Override
 public Student selectById(Integer id) {
  InputStream is = null;
  SqlSession sqlSession = null;
  Student stu = null;
  try{
   is = Resources.getResourceAsStream("MyBatisConfig.xml");
   SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
   sqlSession = sqlSessionFactory.openSession(true);
   stu = sqlSession.selectOne("StudentMapper.selectById",id);
  }catch (Exception e){
   e.printStackTrace();
  }finally {
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if(sqlSession != null){
    sqlSession.close();
   }
  }
  return stu;
 }

 @Override
 public Integer insert(Student stu) {
  InputStream is = null;
  SqlSession sqlSession = null;
  Integer result = null;
  try{
   is = Resources.getResourceAsStream("MyBatisConfig.xml");
   SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
   sqlSession = sqlSessionFactory.openSession(true);
   result = sqlSession.insert("StudentMapper.insert",stu);
  }catch (Exception e){
   e.printStackTrace();
  }finally {
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if(sqlSession != null){
    sqlSession.close();
   }
  }
  return result;
 }

 @Override
 public Integer update(Student stu) {
  InputStream is = null;
  SqlSession sqlSession = null;
  Integer result = null;
  try{
   is = Resources.getResourceAsStream("MyBatisConfig.xml");
   SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
   sqlSession = sqlSessionFactory.openSession(true);
   result = sqlSession.update("StudentMapper.update",stu);
  }catch (Exception e){
   e.printStackTrace();
  }finally {
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if(sqlSession != null){
    sqlSession.close();
   }
  }
  return result;
 }

 @Override
 public Integer delete(Integer id) {
  InputStream is = null;
  SqlSession sqlSession = null;
  Integer result = null;
  try{
   is = Resources.getResourceAsStream("MyBatisConfig.xml");
   SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
   sqlSession = sqlSessionFactory.openSession(true);
   result = sqlSession.delete("StudentMapper.delete",id);
  }catch (Exception e){
   e.printStackTrace();
  }finally {
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if(sqlSession != null){
    sqlSession.close();
   }
  }
  return result;
 }
}
package mybatis.study.service;

import mybatis.study.bean.Student;

import java.util.List;
public interface StudentService {
 // 查询全部
 public abstract List selectAll();

 // 根据id查询
 public abstract Student selectById(Integer id);

 // 新增数据
 public abstract Integer insert(Student stu);

 // 修改数据
 public abstract Integer update(Student stu);

 // 删除数据
 public abstract Integer delete(Integer id);
}
package mybatis.study.service.impl;

import mybatis.study.bean.Student;
import mybatis.study.mapper.StudentMapper;
import mybatis.study.mapper.impl.StudentMapperImpl;
import mybatis.study.service.StudentService;

import java.util.List;

public class StudentServiceImpl implements StudentService {
 // 创建持久层对象
 private StudentMapper mapper = ne StudentMapperImpl();

 @Override
 public List selectAll() {
  return mapper.selectAll();
 }

 @Override
 public Student selectById(Integer id) {
  return mapper.selectById(id);
 }

 @Override
 public Integer insert(Student stu) {
  return mapper.insert(stu);
 }

 @Override
 public Integer update(Student stu) {
  return mapper.update(stu);
 }

 @Override
 public Integer delete(Integer id) {
  return mapper.delete(id);
 }
}
package mybatis.study.controller;

import mybatis.study.bean.Student;
import mybatis.study.service.StudentService;
import mybatis.study.service.impl.StudentServiceImpl;
import .junit.Test;

import java.util.List;


public class StudentController {
 // 创建业务层对象
 private StudentService service = ne StudentServiceImpl();

 @Test
 public void selectAll(){
  List stus = service.selectAll();
  for(Student stu : stus){
   System.out.println(stu);
  }
 }

 @Test
 public void selectById(){
  Student stu = service.selectById(5);
  System.out.println(stu);
 }

 @Test
 public void insert(){
  Student stu = ne Student(5,"赵六",46);
  Integer result = service.insert(stu);
  System.out.println(result);
 }

 @Test
 public void delete(){
  Integer result = service.delete(5);
  System.out.println(result);
 }

 @Test
 public void update(){
  Student stu = ne Student(5,"赵六六",36);
  Integer result = service.update(stu);
  System.out.println(result);
 }
}

LOG4J

在日常开发过程中,排查问题时难免需要输出 MyBatis 真正执行的 SQL语句、参数、结果等信息,我们就可以借助 LOG4J 的功能来实现执行信息的输出使用步骤

    导入jar 包修改核心配置文件
    
    	
    
    
    在 src下编写LOG4J 配置文件
    # Global logging configuration
    # 输出信息的显示。四个级别ERROR、WARN、INFO、DEBUG
    log4j.rootLogger=DEBUG, stdout
    # Console output...
    log4j.appender.stdout=.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    
接口代理方式

传统方式实现Dao层,我们既需要写接口,还要写实现类。而MyBatis 框架可以帮助我们省略编写 Dao层接口实现类的步骤。程序员只需要编写接口,由MyBatis 框架根据接口的定义来创建该接口的动态代理对象

实现规则

    映射配置文件中的名称空间必须和 Dao 层接口的全类名相同映射配置文件中的增删改查标签的id属性必须和Dao层接口的方法名相同映射配置文件中的增删改查标签的 parameterType 属性必须和 Dao层 接口方法的参数相同映射配置文件中的增删改查标签的resultType 属性必须和 Dao层 接口方法的返回值相同

代码实现

    删除mapper层接口的实现类修改映射配置文件修改service 层接口的实现类,采用接口代理方式实现功能
 
 
 
 
  
   SELECT  FROM student WHERe id = #{id}
  
  
   INSERT INTO student VALUES (#{id},#{name},#{age})
  
  
   UPDATE student SET name = #{name},age = #{age} WHERe id = #{id}
  
  
   DELETE FROM student WHERe id = #{id}
  
 
 @Override
 public List selectAll() {
  InputStream is = null;
  List list = null;
  SqlSession sqlSession = null;
  try{
   // 1.加载核心配置文件
   is = Resources.getResourceAsStream("MyBatisConfig.xml");
   // 2. 获取SqlSessionFactory 工厂对象
   SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
   // 3. 获取SqlSession对象
   sqlSession = sqlSessionFactory.openSession(true);
   // 4.获取StudentMapper持久层接口的实现类对象
   StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
   // 5.通过实现类对象调用方法,接收结果
   list = mapper.selectAll();
  }catch (Exception e){
   e.printStackTrace();
  }finally {
   // 6.释放资源
   if(sqlSession != null){
    sqlSession.close();
   }
   if(is != null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
  return list;
 }

通过动态代理开发模式,我们只编写一个接口,不写实现类,我们通过 getMapper()方法最终获取到.apache.ibatis.binding.MapperProxy 代理对象,然后执行功能,而这个代理对象正是 MyBatis 使用了 JDK 的动态代理技术,帮助我们生成了代理实现类对象,从而可以进行相关持久化操作

动态代理实现类对象在执行方法的时候最终调用了 mapperMethod.execute() 方法,这个方法中通过 sitch语句根据操作类型来判断是新增、修改、删除、查询操作,一步回到了 MyBatis 最原生的 SqlSession 方式来执行增删改查


动态sql

MyBatis 映射配置文件中,前面使用的SQL 都是比较简单的,有时候业务逻辑复杂时,我们的 SQL就是动态变化的,此时前面学习的 SQL 就不能满足需求了多条件查询
SELECT FROM student WHERe id = ? AND name = ? AND age = ?
SELECt FROM student WHERe id = ? AND name = ?动态SQL 标签
条件判断标签
循环遍历标签 if标签

条件标签。如果有动态条件,则使用该标签代替here 关键字条件判断标签


 查询条件拼接


 SELECT  FROM student
 
  
   id = #{id}
  
  
   AND name = #{name}
  
  
   AND age = #{age}
  
 

foreach标签

循环遍历标签。适用于多个参数或者的关系


 获取参数

属性
collection参数容器类型,(list-集合,array-数组)
open开始的 SQL 语句
close结束的 SQL 语句
item参数变量名
separator分隔符



分页插件

分页可以将很多条结果进行分页显示如果当前在第一页,则没有上一页。如果在一页,则没有下一页需要明确当前是第几页,这一页中显示多少条结果

在企业级的开发中,分页也是一种常见的技术。而目前使用的 MyBatis 是不带分页功能的,如果想实现分页的功能,需要我们手动编写 LIMIT 语句。不同的数据库实现分页的 SQL 语句也是不同的,所以手写分页成本较高。这个时候可以借助分页插件来帮助我们实现分页功能

PageHelper第三方分页助手。将复杂的分页操作进行封装,从而让分页功能变得非常简单

分页插件实现步骤

    导入jar 包pagehelper-5.1.10.jar jsqlparser-3.1.jar在核心配置文件中集成分页助手插件在测试类中使用分页助手相关 API 实现分页功能

 

分页参数的获取

PageInfo封装分页相关参数的功能类核心方法 返回值方法名说明longgetTotal()获取总条数intgetPages()获取总页数intgetPageNum()获取当前页intgetPageSize()获取每页显示条数intgetPrePage()获取上一页intgetNextPage()获取下一页booleanisIsFirstPage()获取是否是第一页booleanisIsLastPage()获取是否是一页

@Test
public void selectPaging() thros IOException {
 InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
 SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
 SqlSession sqlSession = sqlSessionFactory.openSession(true);
 StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

 // 通过分页助手实现分页功能
 // 参数当前页,显示的条数
 PageHelper.startPage(1,3);

 List list = mapper.selectAll();
 for(Student stu : students){
  System.out.println(stu);
 }

 //获取分页相关参数
 PageInfo info = ne PageInfo<>(list);
 
 System.out.println("总条数" + info.getTotal());
 System.out.println("总页数" + info.getPages());
 System.out.println("当前页" + info.getPageNum());
 System.out.println("每页条数" + info.getPageSize());
 System.out.println("上一页" + info.getPrePage());
 System.out.println("下一页" + info.getNextPage());
 System.out.println("是否是第一页" + info.isIsFirstPage());
 System.out.println("是否是一页" + info.isIsLastPage());

 sqlSession.close();
 is.close();
}

多表操作

我们之前学习的都是基于单表操作的,二实际开发中,随着业务逻辑难度的加深,肯定需要多表操作的多表模型的分类

一对一在任意一方建立外键,关联对方的主键一对多在多的一方建立外键,关联少的一方的主键多对多借助中间表,中间表至少两个字段,分别关联两张表的主键 一对一

一对一模型人和身份证,是一对一的关系数据准备

CREATE DATAbase db12;
USE db12;
CREATE TABLE person(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	age INT
);
INSERT INTO person VALUES (NULL,'张三',23),(NULL,'李四',24),(NULL,'王五',25);
CREATE TABLE card(
	id INT PRIMARY KEY AUTO_INCREMENT,
	number VARCHAR(30),
	pid INT,
	CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id)
);
INSERT INTO card VALUES (NULL,'12345',1),(NULL,'23456',2),(NULL,'34567',3);
映射配置文件



 
 
  
  
  
  
   
   
   
  
 
 
  SELECT c.id cid,c.name ame,s.id sid, s.name sname,s.age sage FROM classes c,student s WHERe c.id = s.cid;
 

@Test
 public void selectAll() thros IOException {
  InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
  SqlSessionFactory sqlSessionFactory = ne SqlSessionFactoryBuilder().build(is);
  SqlSession sqlSession = sqlSessionFactory.openSession(true);
  OneToManyMapper mapper = sqlSession.getMapper(OneToManyMapper.class);
  List classes = mapper.selectAll();
  for(Classes cls : classes){
   System.out.println(cls.getId() + "," + cls.getName());
   List students = cls.getStudents();
   for(Student stu : students){
    System.out.println("t" + stu);
   }
  }
 }

配置字段和对象属性的映射关系标签
id属性唯一标识
type属性实体对象类型配置主键映射的关系标签配置非主键映射关系标签
column属性表中字段名称
property属性实体对象变量名称配置被包含集合对象的映射关系标签
property属性被包含集合对象的变量名
ofType属性集合中保存的对象数据类型 多对多

多对多模型学生和课程,一个学生可以选择多门课程,一个课程也可以被多个学生所选择数据准备

CREATE TABLE course(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)
);
INSERT INTO course VALUES (NULL,'语文'),(NULL,'数学');
CREATE TABLE stu_cr(
	id INT PRIMARY KEY AUTO_INCREMENT,
	sid INT,
	cid INT,
	CONSTRAINT sc_fk1 FOREIGN KEY (sid) REFERENCES student(id),
	CONSTRAINT sc_fk2 FOREIGN KEY (cid) REFERENCES course(id)
);
INSERT INTO stu_cr VALUES (NULL,1,1),(NULL,1,2),(NULL,2,1),(NULL,2,2);
映射配置文件



 
  
  
  
  
  
   
   
  
 
 
 
        
        
      
    
  • 电脑维修导航

  • 电脑维修知识

  • 笔记本电脑维修

  • 电脑维修培训

  • Copyright © 2016-2025 www.caominkang.com 曹敏电脑维修网 版权所有 Power by