mybatis的增删改查有几种方式
IDEA创建项目时目录结构及配置文件
<dependencies>
<!--通用mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.1.5</version>
</dependency>
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- 连接诶mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<!-- log4j 日志依赖 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--插件依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
</dependencies>
jdbc.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_mapper?useUnicode=true&characterEncoding=UTF-8&&serverTimezone=Hongkong&useSSL=false
username=root
password=root
log4j.properties文件
### 设置###
# debug 日志级别,常用的4个日志级别:ERROR、WARN、 INFO、DEBUG
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
注意要:必须要把接口的那个包设置进来
mybatis.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入 -->
<properties resource="jdbc.properties"></properties>
<!--开启驼峰映射-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--分页插件-->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 选择mysql数据库的分页方式 -->
<property name="helperDialect" value="mysql"/>
<property name="rowBoundsWithCount" value="true"/>
</plugin>
</plugins>
<!-- 配置环境,连接需要的基本参数 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(配置连接) -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载映射文件的位置 接口的包-->
<package name="Mybatis.Mapper"/>
<package name="com.czxy.mapper"/>
</mappers>
</configuration>
注意mybaits.xml的路径对应上不然读取不到文件
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import java.io.IOException;
import java.io.Reader;
public class MyBatisMapperUtils {
private static SqlSessionFactory sqlSessionFactory = null;
/*
* 创建本地线程变量,为每一个线程独立管理一个session对象 每一个线程只有且仅有单独且唯一的一个session对象
* 使用ThreadLocal对session进行管理,可以保证线程安全,避免多实例同时调用同一个session对象
*/
private static ThreadLocal<SqlSession> threadlocal = new ThreadLocal<SqlSession>();
// 创建sessionFactory对象,因为整个应用程序只需要一个实例工厂
// 而静态代码块随着类的加载而执行,而且只执行一次,因此放入静态代码块中初始化工厂实例
static {
try {
//读取配置文件
Reader reader = Resources.getResourceAsReader("mybatis.xml");
//创建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
//关闭读取流
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 新建session会话,并把session放在线程变量中
*/
private static void newSession() {
//从刚刚创建的 sqlSessionFactory 中获取 session
SqlSession session = sqlSessionFactory.openSession();
//创建一个MapperHelper
MapperHelper mapperHelper = new MapperHelper();
//配置 mapperHelper 后,执行下面的操作
mapperHelper.processConfiguration(session.getConfiguration());
// 将session会话保存在本线程变量中
threadlocal.set(session);
}
/**
* 返回session对象
* @return session
*/
public static SqlSession getSession(){
//优先从线程变量中取session对象
SqlSession session = threadlocal.get();
//如果线程变量中的session为null,
if(session==null){
//新建session会话,并把session放在线程变量中
newSession();
//再次从线程变量中取session对象
session = threadlocal.get();
}
return session;
}
/**
* 关闭session对象,并从线程变量中删除
*/
public static void closeSession(){
//读取出线程变量中session对象
SqlSession session = threadlocal.get();
//如果session对象不为空,关闭sessoin对象,并清空线程变量
if(session!=null){
session.close();
threadlocal.set(null);
}
}
/**
* 提交并关闭资源
*/
public static void commitAndclose() {
//获取连接
SqlSession openSession = getSession();
//非空判断
if(openSession!=null) {
//提交
openSession.commit();
//关闭资源
openSession.close();
//从threadlocal中移除session
threadlocal.remove();
}
}
}
属性和表的字段 要么驼峰映射 ,要么书写的和表的字段一样
第一种 多个参数进行传递
注意:给sql赋值时@param的名字必须要与传入#{}里面的一样,前面调用时不需要注意这个字段,只要注意类型
第二种一个map 进行传递
注意:map传递设置的key名字必须要和传入#{}里面的一样
第三种一个pojo(对象)传递
传递的参数对象的属性名字必须要和#{}里面一样
SQL 自己手写
@Select("SELECT brand_id,brand_name,brand_img,create_time,data_flag FROM brands WHERE brand_id = #{bid}")
public Map<String,Object> selectBrandById(Integer brandid);
@ResultMap 当多个方法返回结果需要用到这些重复字段时,可以调用上此次的
订单 与用户 代码
/* 映射的用户为空 原因是用了通用mapper 用户类的id没有使用注解*/
@Select("SELECT \n" +
"o.order_id,\n" +
"o.user_id,\n" +
"o.order_price,\n" +
"o.payment,\n" +
"o.state,\n" +
"o.order_createtime,\n" +
"o.note,\n" +
"u.username,\n" +
"u.phone\n" +
"FROM orders o JOIN `user` u\n" +
"ON o.user_id=u.uid AND order_id=#{orderId};")
@Results(id = "selectUser",value = {
@Result(property = "orderId",column ="order_id",id = true),
@Result(property = "userId",column = "user_id"),
@Result(property = "orderPrice",column = "order_price"),
@Result(property = "payment",column = "payment"),
@Result(property = "state",column = "state"),
@Result(property = "orderCreatetime",column = "order_createtime"),
@Result(property = "note",column = "note"),
/*多对一*/
// @Result(property ="user" ,column = "user_id" ,one = @One(select ="Mybatis.Mapper.UserMapper.findByUid"))
@Result(property ="users" ,column = "user_id" ,one = @One(select ="Mybatis.Mapper.UserMapper.selectByPrimaryKey"))
})
public Orders findOrderByOrderId(@Param("orderId") Integer orderId);
另一部分
@Select("SELECT * FROM `user` WHERE uid=#{uid}")
public User findByUid(@Param("uid") int uid);
总结 :多个对一个
1返回的结果是一个对象
2些sql时两表关联,用订单id查询 ,然后在用用户id查询一次,相当于查询了两次,所用的对应关系是 one =@One ,第二次查询时使用表的字段区查询,不然没数据,记得标记主键,记得二次查询的时候返回的结果字段明不用些错了 对象的值 users
代码
```java
// 多对一
@Select("SELECT\n" +
"u.uid,\n" +
"u.username,\n" +
"u.sex,\n" +
"u.birthday,\n" +
"u.phone,\n" +
"u.address,\n" +
"o.order_id,\n" +
"o.user_id,\n" +
"o.order_price,\n" +
"o.state,\n" +
"o.order_createtime,\n" +
"o.note\n" +
"FROM `user` u JOIN orders o\n" +
"ON u.uid=o.user_id AND u.uid=#{uid}")
/* 返回错了*/
@Results(id = "selectUser" ,value = {
@Result(property = "uid",column = "uid" ,id = true),
@Result(property = "username",column = "username"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "phone",column = "phone"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "orders",column ="order_id",many = @Many(select = "Mybatis.Mapper.OrderMapper.findByUserId"))
})
public List<User> findUserByUid(@Param("uid") int uid);
```java
// 不是用uid查
@Select("select * from orders where order_id=#{order_id}")
public List findByUserId(@Param("order_id") int orderId);
总结
1返回的结果是集合
2两表关联查询先用用户id查询 ,二次查询再用订单id查询,many =@many
返回的 传递的 查询的
字段
1自动驼峰映射
2忽略大小写
1 在每个实体类写
@Table(name = “sys_user”)
2 一个实体类需要把Id标注出来需要用 @Id
3 当实体类的属性明和表的字段明不一样时 使用 @Column 进行映射上
4在查询时用不到,但是实体类需要这个字段时 ,其实就是实体类的字段和表中的字段不对应 ,就在实体类的不要查询的字段上些@Transient
通用mapper 的增删改查 推荐的用法
// 查询 selectOne
@Test
public void selectOne() {
SqlSession session = MyBatisMapperUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
// 传进去的都是些条件 设置的是一个用户需要同时 满足
user.setUid(2);
user.setSex("1");
User one = mapper.selectOne(user);
System.out.println(one);
}
/**
* 根据主键查询
* 查询所有
*
* 通用mapper 不能进行模糊查询 ,也不能查询某个属性值小于或者等于
*/
@Test
public void selecttwo() {
SqlSession session = MyBatisMapperUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
/* User user = mapper.selectByPrimaryKey(2);*/
// List userlist = mapper.selectAll();
User nulluser = new User();
nulluser.setSex("2");
nulluser.setAddress("江苏南京");
List<User> userlist = mapper.select(nulluser);
for (User user : userlist) {
System.out.println(user);
}
}
/* 查询*/
@Test
public void selectthree(){
SqlSession session = MyBatisMapperUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user=new User();
/* user.getUid();*/
int num = mapper.selectCount(user);
System.out.println("一共"+num);
}
要提交事务 ,条件就是设置的属性值
public void insertOne() {
SqlSession session = MyBatisMapperUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("mangseng2");
/* user.setAddress("beijing");
user.setPhone("11223366");*/
// user.setBirthday(new Date());
// 添加 ,没设置的值为null
// 第一种方式
mapper.insert(user);
//第二种方式
// 没有事务提交
// mapper.insertSelective(user);
session.commit();
session.close();
}
要提交事务,切记要写条件,条件就是设置的属性值,不写条件回更新所有
@Test
public void updateOne() {
SqlSession session = MyBatisMapperUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
// 更行时有条件
// 第一种方式
User user = new User();
// 条件
user.setUid(2);
user.setUsername("瑶瑶");
// 第二种方式
user.setAddress("湖南");
mapper.updateByPrimaryKeySelective(user);
// 第一种方式 不建议推荐
// mapper.updateByPrimaryKey(user);
session.commit();
session.close();
}
提交事务 ,切记要些条件,不写条件会删掉所有
@Test
public void deleteOne(){
SqlSession session = MyBatisMapperUtils.getSession();
UserMapper mapper = session.getMapper(UserMapper.class);
// 第一种方式 根据条件删除
User user=new User();
user.setUid(1);
/* user.setSex("2");
user.setAddress("湖南");*/
// mapper.delete(user);
// 第二种
// mapper.deleteByPrimaryKey(2);
session.commit();
session.close();
}
作用:大于 小于 模糊 专查某个字段的值 排序 动态sql 就是if 条件判断
使用步骤 :创建Example 对象 ,通过Example 对象创建条件对象 ,然后直接调用方法,调用一次 criteria.andGreaterThan 就相当于添加一个条件,切记这里所使用的字段都是实体类属性的字段,所有的条件写好后,调用mapper的example方法 返回结果
排序例子 example.orderBy(“brandId”).desc();
查询属性的方法
代码
/*根据品牌名称模糊查询,根据创建日期进行范围查询*/
@Test
public void ExampleSelect2() throws ParseException {
SqlSession session = MyBatisMapperUtils.getSession();
BrandMapper mapper = session.getMapper(BrandMapper.class);
// 使用 example 进行查询
Example example = new Example(Brands.class);
Example.Criteria criteria = example.createCriteria();
Brands brands=new Brands();
brands.setBrandName("%"+"百草"+"%");
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
Date start = dateFormat.parse("2020-1-10");
Date end = dateFormat.parse("2020-10-15");
brands.setStartTime(start);
brands.setEndTime(end);
// 动态sql 三个条件
if(brands.getBrandName()!=null&&!brands.getBrandName().equals("")){
criteria.andLike("brandName",brands.getBrandName());
}
// 如果前面为空和下面为空 单独查询这个
// 如果下面不为空 查询这个和下面这个
//tk.mybatis.mapper.MapperException: 当前实体类不包含名为startTime的属性!
if(brands.getStartTime()!=null){
criteria.andGreaterThanOrEqualTo("createTime",brands.getStartTime());
}
// 前面两个为空 就单独查询这个
if (brands.getEndTime()!=null){
criteria.andLessThanOrEqualTo("createTime",brands.getEndTime());
}
//条件设置好了
List<Brands> filter = mapper.selectByExample(example);
for (Brands b : filter) {
System.out.println(b);
}
session.close();
}
//查询ID > 1 并且 小于等于 3 或者ID 大于5的品牌,结果按照品牌ID降序排序
/* example 适合运用 大于小于 模糊 在什么什么之间 同时 或者 就是where 后面的条件 or and 可以排序 根据主键查询 */
@Test
public void ExampleSelect() {
SqlSession session = MyBatisMapperUtils.getSession();
BrandMapper mapper = session.getMapper(BrandMapper.class);
Example example = new Example(Brands.class);
// 设置条件的
Example.Criteria criteria = example.createCriteria();
// 类的字段 不是自定义的字段
criteria.andGreaterThan("brandId", 1);
criteria.andLessThanOrEqualTo("brandId", 3);
criteria.orGreaterThanOrEqualTo("brandId", 5);
// or 之前的条件时连续的同时满足的
example.orderBy("brandId").desc();
List<Brands> brands = mapper.selectByExample(example);
// 通过这个查Example 查询
for (Brands brand : brands) {
System.out.println(brand);
}
session.close();
}
resultType 一个类用这
resultMap 一个类包含另外一个类用这个
项目结构
mybatis的配置文件
注意三个地方 查询后结果起别名 ,每个xml的相对路径写到mapper里面
,驼峰映射
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入 -->
<properties resource="jdbc.properties"></properties>
<!--开启驼峰映射-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<!-- 写的是 每个类首字母的小写-->
<package name="com.czxy.model"/>
<package name="com.czxy.Vo"/>
</typeAliases>
<!-- 配置环境,连接需要的基本参数 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(配置连接) -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 加载映射文件的位置
-->
<mapper resource="mapper/UserMapper.xml"></mapper>
<mapper resource="mapper/UserMapperDao.xml"></mapper>
<mapper resource="mapper/BrandMapperDao.xml"></mapper>
<!--通用mapper-->
<package name="com.czxy.TY.mapper"/>
</mappers>
</configuration>
注意就是
1 每个xml的namespace 都需要写上对应接口的名字的相对路径
多对一的代码xml
resultMap接收 ,查询一次 先填充 order ,在填充user
<!--1111111111111111111-->
<resultMap id="selectOne" type="orders" extends="f01">
<!-- 冗余代码-->
<!--<id property="orderId" column="order_id"></id>
<result property="userId" column="user_id"></result>
<result property="orderPrice" column="order_price"></result>
<result property="payment" column="paument"></result>
<result property="state" column="state"></result>
<result property="orderCreateTime" column="order_createtime"></result>
<result property="note" column="note"></result>-->
<!-- 对应关系
对一 association
对多 collection
-->
<association property="user">
<id property="uid" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="phone" column="phone"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</association>
</resultMap>
<select id="listOrderAndUser" resultMap="selectOne">
SELECT
o.order_id,
o.user_id,
o.order_price,
o.payment,
o.note,
o.state,
o.order_createtime,
u.username,
u.phone
FROM orders o JOIN `user` u
ON o.user_id=u.uid;
</select>
嵌套查询 在 association 里面在查询一次,使用的时表的字段,查询两次
注意 防止包空 查询的返回结果
javaType=“user”
<!--2222222222222222222222222-->
<resultMap id="selectOne02" type="orders" extends="f01">
<!-- 冗余代码-->
<!-- <id property="orderId" column="order_id"></id>
<result property="userId" column="user_id"></result>
<result property="orderPrice" column="order_price"></result>
<result property="payment" column="payment"></result>
<result property="state" column="state"></result>
<result property="orderCreatetime" column="order_createtime"></result>
<result property="note" column="note"></result>-->
<!-- 查询订单时 同时查询用户 用的是订单的userId -->
<association property="user" select="selectUserByID" column="user_id">
</association>
</resultMap>
<select id="selectUserByID" resultType="user">
SELECT
uid,
username,
phone
FROM
`user`
WHERE
uid=#{uid}
</select>
<select id="listOrderBySelect" resultMap="selectOne02">
SELECT
o.order_id,
o.user_id,
o.order_price,
o.payment,
o.note,
o.state,
o.order_createtime,
u.username,
u.phone
FROM orders o JOIN `user` u
ON o.user_id=u.uid;
</select>
使用过Vo ,查询的结果 返回给Vo ,查询一次
<!--33333333333333333333333-->
<select id="listOrderAndReturnOrdersVO" resultType="OrderVo" >
SELECT
o.order_id,
o.user_id,
o.order_price,
o.payment,
o.note,
o.state,
o.order_createtime,
u.username,
u.phone
FROM orders o JOIN `user` u
ON o.user_id=u.uid;
</select>
实体VO
public class OrderVo extends Orders {
private String username;
private String phone;
public OrderVo() {
}
public OrderVo(String username, String phone) {
this.username = username;
this.phone = phone;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
一对多
返回的集合需要些 类型 oftype=xxx,防止报空 ,查询一次
<!-- 1111111111111111111111111111 -->
<resultMap id="brandAndProducesMap" type="brands">
<id property="brandId" column="brand_id"></id>
<result property="brandName" column="brand_name"></result>
<result property="brandImg" column="brand_img"></result>
<!--一对多 collection 防止报空 必须写ofType 指定集合类型 -->
<collection property="listProduct" ofType="product"> <!--listProduct-->
<id property="productId" column="product_id"></id>
<result property="productImg" column="product_img"></result>
<result property="productName" column="product_name"></result>
<result property="productSale" column="product_sale"></result>
<result property="productPrice" column="product_price"></result>
</collection>
</resultMap>
<!--Exception in thread "main" org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2-->
<select id="selectBrandListProduct" resultMap="brandAndProducesMap">
SELECT
b.brand_id,
b.brand_name,
b.brand_img,
p.product_id,
p.product_img,
p.product_name,
p.product_sale,
p.stock,
p.product_price,
p.brandid
FROM
brands b JOIN product p
ON b.brand_id=p.brandid
</select>
多个类 resultMap—>type
一个类---->resulttype
<!-- 22222222222-->
<resultMap id="baseResultMap" type="brands">
<id property="brandId" column="brand_id"></id>
<result property="brandName" column="brand_name"></result>
<result property="brandImg" column="brand_img"></result>
</resultMap>
<resultMap id="resultMapBySelect" type="brands" extends="baseResultMap">
<collection property="listProduct" column="brand_id" select="listProductsByBrandID"></collection>
</resultMap>
<select id="listProductsByBrandID" resultType="product">
SELECT
product_id,
product_img,
product_name,
product_sale,
stock,
product_price,
brandid
FROM product
WHERE brandid = #{brandID}
</select>
<select id="selectBrandAndListProducts" resultMap="resultMapBySelect" >
SELECT
brand_id,
brand_img,
brand_name
FROM
brands
WHERE
brand_id=#{brand_id}
</select>
/*Table structure for table `tab_student` */
DROP TABLE IF EXISTS `tab_student`;
CREATE TABLE `tab_student` (
`sid` int NOT NULL AUTO_INCREMENT COMMENT '学生ID',
`student_name` varchar(30) DEFAULT NULL COMMENT '姓名',
`student_birthday` date DEFAULT NULL COMMENT '生日',
`student_height` double DEFAULT NULL COMMENT '身高',
`sex` varchar(2) DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
/*Data for the table `tab_student` */
insert into `tab_student`(`sid`,`student_name`,`student_birthday`,`student_height`,`sex`) values (1,'褚英才','1997-02-01',175,'男'),(2,'绍洋','1999-08-21',160,'女'),(3,'司徒玉','2000-10-12',162,'女'),(4,'孟杨','1999-06-08',172,'男'),(5,'郎桂芝','1998-10-26',168,'女');
/*Table structure for table `tab_student_teacher` */
DROP TABLE IF EXISTS `tab_student_teacher`;
CREATE TABLE `tab_student_teacher` (
`id` int NOT NULL AUTO_INCREMENT,
`sid` int DEFAULT NULL COMMENT '学生ID',
`tid` varchar(32) DEFAULT NULL COMMENT '老师ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
/*Data for the table `tab_student_teacher` */
insert into `tab_student_teacher`(`id`,`sid`,`tid`) values (1,1,'T001'),(2,2,'T001'),(3,1,'T002'),(4,3,'T002'),(5,5,'T002'),(6,2,'T003');
/*Table structure for table `tab_teacher` */
DROP TABLE IF EXISTS `tab_teacher`;
CREATE TABLE `tab_teacher` (
`tid` varchar(32) NOT NULL COMMENT '老师ID',
`tname` varchar(30) DEFAULT NULL COMMENT '姓名',
`tsex` varchar(3) DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`tid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `tab_teacher` */
insert into `tab_teacher`(`tid`,`tname`,`tsex`) values ('T001','韩老师','男'),('T002','董老师','男'),('T003','茆老师','女');
类
public class Teacher {
private String tid;
private String tname;
private String tsex;
//老师对应多个学生
List stuList = new ArrayList();
//get set...
}
public class Student {
private Integer sid;
private String studentName;
private Date studentBirthday;
private Double studentHeight;
private String sex;
//学生对应多个老师
private List teacherList = new ArrayList<>();
//get set...
}
StudentMapper.xml
<resultMap id="studentBaseMap" type="student">
<id property="sid" column="sid"/>
<result property="studentName" column="student_name"/>
<result property="studentBirthday" column="student_birthday"/>
<result property="studentHeight" column="student_height"/>
<result property="sex" column="sex"/>
<collection property="teacherList" ofType="Teacher">
<id property="tid" column="tid"/>
<result property="tname" column="tname"/>
<result property="tsex" column="tsex"/>
</collection>
</resultMap>
<select id="selectStudentAndTeachers" resultMap="studentBaseMap">
SELECT
s.sid,
s.student_name,
s.student_birthday,
s.student_height,
s.sex,
t.tid,
t.tname,
t.tsex
FROM tab_student s,tab_student_teacher st,tab_teacher t
WHERE s.sid = st.sid
AND st.tid = t.tid
AND s.sid = #{sid}
</select>
总结