MyBatis中的多表操作
一对一(数据准备)
核心配置文件准备:每一张表对应的实体类放在一个包(bean)下,使用标签typeAliases指定这些实体类的别名(就是类名),在映射文件中直接写类的名字就可以了,可以小写,mappers标签引入映射文件的包名加文件名。
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration 核心根标签-->
<configuration>
<!--引入数据库连接的配置文件-->
<properties resource="jdbc.properties"/>
<!--配置LOG4J-->
<settings>
<setting name="logImpl" value="log4j"/>
</settings>
<!--起别名-->
<typeAliases>
<package name="com.itheima.bean"/>
</typeAliases>
<!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个-->
<environments default="mysql">
<!--environment配置数据库环境 id属性唯一标识-->
<environment id="mysql">
<!-- transactionManager事务管理。 type属性,采用JDBC默认的事务-->
<transactionManager type="JDBC"></transactionManager>
<!-- dataSource数据源信息 type属性 连接池-->
<dataSource type="POOLED">
<!-- property获取数据库连接的配置信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!-- mappers引入映射配置文件 -->
<mappers>
<mapper resource="com/itheima/one_to_one/OneToOneMapper.xml"/>
</mappers>
</configuration>
映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.table01.OneToOneMapper">
<!--配置字段和实体对象属性的映射关系-->
<!-- <resultMap id="oneToOne" type="card">
<id column="cid" property="id" />
<result column="number" property="number" />-->
<!--
association:配置被包含对象的映射关系
property:被包含对象的变量名
javaType:被包含对象的数据类型
-->
<!-- <association property="p" javaType="person">
<id column="pid" property="id" />
<result column="name" property="name" />
<result column="age" property="age" />
</association>
</resultMap>-->
<resultMap id="oneToOne" type="card">
<id column="cid" property="id"/>
<result column="number" property="number"/>
<association property="p" javaType="person">
<id column="pid" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</association>
</resultMap>
<select id="selectAll" resultMap="oneToOne">
SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
</select>
</mapper>
映射接口
package com.itheima.table01;
import com.itheima.bean.Card;
import java.util.List;
public interface OneToOneMapper {
//查询全部
public abstract List<Card> selectAll();
}
一对一操作实现需要的步骤
1.一张表对应一个实体类,这里实体类就有两个,就需要定义两个实体类,一对一的关系中,哪张表都可以作为主表或者从表,如果作为主表,成员变量中必须一个从表实体类对象,因为要通过java代码来获取到他们之间的对应关系。
package com.itheima.bean;
public class Card {
private Integer id; //主键id
private String number; //身份证号
private Person p; //所属人的对象
身份证表的实体类作为主表,一个身份证对应一个人,所以需要定义成员变量Person类。
public class Person {
private Integer id; //主键id
private String name; //人的姓名
private Integer age; //人的年龄
实体类人的三个数据
2.定义一个接口,接口中定义你需要查询的内容。
package com.itheima.table01;
import com.itheima.bean.Card;
import java.util.List;
public interface OneToOneMapper {
//查询全部
public abstract List<Card> selectAll();
}
查询全部,返回一个card集合,因为这里card这张表作为了主表,查询出来有多个card对象,用list封装,一个card对应了一个person。
3.编写映射文件,写对应的sql语句,将查询出的数据封装到定义的实体类中。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.table01.OneToOneMapper">
<!--配置字段和实体对象属性的映射关系-->
<resultMap id="oneToOne" type="card">
<id column="cid" property="id" />
<result column="number" property="number" />
<!-- association:配置被包含对象的映射关系
property:被包含对象的变量名
javaType:被包含对象的数据类型-->
<association property="p" javaType="person">
<id column="pid" property="id" />
<result column="name" property="name" />
<result column="age" property="age" />
</association>
</resultMap>
<select id="selectAll" resultMap="oneToOne">
SELECT c.id cid,number,pid,NAME,age FROM card c,person p WHERE c.pid=p.id
</select>
</mapper>
select标签:id属性就是对应接口的方法名,必须一致mybatis才能通过接口代理的方式获取方法体的内容。标签中的内容写对应的sql语句。这里是一对一的关系,返回值的类型为card,card中有person的成员变量,mybatis就无法自动的封装,必须手动封装。返回值类型就用resultMap属性,后面跟一个名字。具体是甚麽类型需要在select标签上面表明出来。
resultMap标签:id属性就对应了下面resultMap的名字,type属性就是返回值类型card,下面写的就是card类中的属性,id标签就是主键对应,result标签是其他属性对应。每一个都有column属性(sql查询出数据的列名)对应property属性(实体类中的变量名)。
association:这个标签代表card表中的成员变量有引用数据,需要写在这个标签下,中间的内容与person类中一一对应。
4.测试类中使用接口代理sqlsession的getMapper方法获取接口的实现类,再使用这个实现类重写的方法返回card集合并打印。
package com.itheima.table01;
import com.itheima.bean.Card;
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 org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class Test01 {
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取OneToOneMapper接口的实现类对象
OneToOneMapper mapper = sqlSession.getMapper(OneToOneMapper.class);
//5.调用实现类的方法,接收结果
List<Card> list = mapper.selectAll();
//6.处理结果
for (Card c : list) {
System.out.println(c);
}
//7.释放资源
sqlSession.close();
is.close();
}
}
一对多
collection标签,因为一对多是一个对象集合对应了多个对象,映射文件中对应的时候,就应该用collection标签,在标签中也试一一对应的关系。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.table02.OneToManyMapper">
<!-- <resultMap id="oneToMany" type="classes">
<id column="cid" property="id"/>
<result column="cname" property="name"/>-->
<!--
collection:配置被包含的集合对象映射关系
property:被包含对象的变量名
ofType:被包含对象的实际数据类型
-->
<!-- <collection property="students" ofType="student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
</collection>
</resultMap>-->
<resultMap id="oneToMany" type="classes">
<id column="cid" property="id"/>
<result column="cname" property="name"/>
<collection property="students" ofType="student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
</collection>
</resultMap>
<select id="selectAll" resultMap="oneToMany">
SELECT c.id cid,c.name cname,s.id sid,s.name sname,s.age sage FROM classes c,student s WHERE c.id=s.cid
</select>
</mapper>
多对多
用法跟一对多是一样的,唯一的区别就是sql语句不同,至少三个表,有个中间表的存在。
MyBatis中使用注解来操作增删改查
基本概念
不需要映射文件,就可以通过java代码查询出来数据封装到实体类,在控制台得到想查询的结果。但是还是要在核心配置文件中的mappers标签中说明映射关系。
注解的使用
基本的增删改查使用@Select,@Delete,@Update,@Insert,这四个注解针对单表查询,括号内双引号里写自己想查询的内容和表格。如果设计到一对多或者多对多注解下还要使用@Results注解,这个注解的内容是一个数组,每个内容要用Result注解。
@Select("select * from classes")
@Results({
@Result(column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(
property = "students",
javaType = List.class,
column = "id",
many = @Many(select = "com.itheima.one_to_many.StudentMapper.selectByCid")
)
})
@Results注解中要写中括号,因为里面是一个数组,当中的@Result对应的就是字段名和实体类的属性一一对应,因为在classes中的最后一个属性是一个实体类类型,所以只用告诉在类中的属性变量名和实际的类型,column属性可以使用在其他接口的方法上。一对一则是one@One(select=包名加类加接口方法),一对多是many@Many,这是固定写法。
在核心配置文件中的写法
<mappers>
<package name="com.itheima"/>
</mappers>
package标签中还是要指定注解的映射关系,这个标签就表示了接口中的方法用注解的方式进行sql语句的查询。就不需要实体映射文件了。