Mybatis 多表间查询之 多对一
0. 描述:
关于是使用MyBatis多表之间的查询操作,案例中表t_category 是描述书的分类,表t_Book是现有书表,两个表之间通过cid字段建立连接,本次通过两种方式来实现 多对一的实现,关联和分步来实现,实际开发中是分布来实现的。
1. 表
CREATE TABLE `t_category` (
`cid` char(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`cname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`cid`) USING BTREE,
UNIQUE INDEX `cname`(`cname`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `t_category` VALUES ('1', '程序设计', '程序设计分类');
INSERT INTO `t_category` VALUES ('3', '图形 图像 多媒体', '图形图像多媒体');
INSERT INTO `t_category` VALUES ('4', '操作系统/系统开发', '操作系统/系统开发');
INSERT INTO `t_category` VALUES ('458795C27E7346A8A5F1B942319297E0', '系统开发', '系统开发分类');
INSERT INTO `t_category` VALUES ('5', '数据库', '数据库');
INSERT INTO `t_category` VALUES ('57DE3C2DDA784B81844029A28217698C', 'Dreamweaver', 'Dreamweaver分类');
INSERT INTO `t_category` VALUES ('5F79D0D246AD4216AC04E9C5FAB3199E', 'Java Javascript', 'Java Javascript分类');
INSERT INTO `t_category` VALUES ('6', '网络与数据通讯', '网络与数据通讯!');
INSERT INTO `t_category` VALUES ('65830AB237EF428BAE9B7ADC78A8D1F6', 'Unix', 'Unix分类');
INSERT INTO `t_category` VALUES ('922E6E2DB04143D39C9DDB26365B3EE8', 'C C++ VC VC++', 'C C++ VC VC++分类');
CREATE TABLE `t_book` (
`bid` char(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`bname` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`author` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`price` decimal(8, 2) DEFAULT NULL,
`press` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`cid` char(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`bid`) USING BTREE,
INDEX `FK_t_book_t_category`(`cid`) USING BTREE,
CONSTRAINT `FK_t_book_t_category` FOREIGN KEY (`cid`) REFERENCES `t_category` (`cid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
INSERT INTO `t_book` VALUES ('52B0EDFF966E4A058BDA5B18EEC698C4', '亮剑Java Web项目开发案例导航(含DVD光盘1张)', '朱雪琴', 69.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('5315DA60D24042889400AD4C93A37501', 'Spring 3.x企业应用开发实战(含CD光盘1张)', '陈雄华', 90.00, '电子工业出版社', '1');
INSERT INTO `t_book` VALUES ('56B1B7D8CD8740B098677C7216A673C4', '疯狂 Java 程序员的基本修养(《疯狂Java讲义》最佳拍档,扫清知识死角,夯实基本功)', '李刚', 59.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('57B6FF1B89C843C38BA39C717FA557D6', '了不起的Node.js: 将JavaScript进行到底(Web开发首选实时 跨多服务器 高并发)', 'Guillermo Rauch', 79.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('5C68141786B84A4CB8929A2415040739', 'JavaScript高级程序设计(第3版)(JavaScript技术名著,国内JavasScript第一书,销量超过8万册)', 'Nicholas C. Zakas', 99.00, '人民邮电出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('5EDB981339C342ED8DB17D5A198D50DC', 'Java程序性能优化', '葛一鸣', 59.00, '清华大学出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('A3D464D1D1344ED5983920B472826730', 'Java Web开发详解:XML+DTD+XML Schema+XSLT+Servlet 3 0+JSP 2 2深入剖析与实例应用(含CD光盘1张)', '孙鑫', 119.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('A46A0F48A4F649AE9008B38EA48FAEBA', 'Java编程全能词典(含DVD光盘2张)', '明日科技', 98.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('D0E69F85ACAB4C15BB40966E5AA545F1', 'Java并发编程实战(第16届Jolt大奖提名图书,Java并发编程必读佳作', 'Brian Goetz', 69.00, '机械工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('D2ABA8B06C524632846F27C34568F3CE', 'Java 经典实例', '达尔文', 98.00, '中国电力出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('D8723405BA054C13B52357B8F6AEEC24', '深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)', '周志明', 79.00, '机械工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('DC36FD53A1514312A0A9ADD53A583886', 'JavaScript异步编程:设计快速响应的网络应用【掌握JavaScript异步编程必杀技,让代码更具响应度! 】', 'Trevor Burnham ', 32.00, '人民邮电出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('DCB64DF0084E486EBF173F729A3A630A', 'Java设计模式(第2版)', 'Steven John Metsker', 75.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('DCB64DF0084E486EBF173F798A3A630A', 'C++ Primer中文版(第5版)', '(美)李普曼 等', 128.00, '电子工业出版社', '922E6E2DB04143D39C9DDB26365B3EE8');
INSERT INTO `t_book` VALUES ('DEE7BDC7E0E343149E3C3601D2658171', '疯狂HTML 5/CSS 3/JavaScript讲义(含CD光盘1张)', '李刚', 69.00, '电子工业出版社', '1');
INSERT INTO `t_book` VALUES ('DF4E74EEE89B43229BB8212F0B858C38', '精通Hibernate:Java对象持久化技术详解(第2版)(含光盘1张)', '孙卫琴', 75.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('EA695342393C4BE48B831FA5E6B0E5C4', '编写可维护的JavaScript《JavaScript高级程序设计》作者Nicholas Zakas最新力作,构建编码风格手册,帮助开发团队从“游击队”走向“正规军”)', 'Nicholas C. Zakas', 55.00, '人民邮电出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('F0E34313BF304CCEBF198BD4E05307B8', 'jQuery Cookbook中文版(jQuery之父鼎力推荐,社区数十位专家倾情力作', 'jQuery社区专家组', 69.00, '人民邮电出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('F6162799E913423EA5CB57BEC65AB1E9', 'JUnit实战(第2版)', '塔凯文', 79.00, '人民邮电出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('F693239BC3B3444C8538ABE7411BB38E', 'Java Web典型模块与项目实战大全(配光盘)', '常建功', 99.50, '清华大学出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('F78C94641DB4475BBA1E72A07DF9B3AE', 'JAVA面向对象编程', '孙卫琴 ', 65.80, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('FC232CD9B6E6411BBBB1A5B781D2C3C9', 'Java与模式(含盘)(超多实例和习题,详解设计原则与设计模式)', '阎宏', 88.00, '电子工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('FEC3740CF30E442A94021911A25EF0D7', 'Spring攻略(第2版)(Spring攻略(第2版))', 'Gary Mak Josh Long Daniel Rubio', 128.00, '人民邮电出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
INSERT INTO `t_book` VALUES ('FFABBED1E5254BC0B2726EC4ED8ACCDA', '深入理解OSGi:Equinox原理、应用与最佳实践(《深入理解Java虚拟机》作者新作!全面解读最新OSGi R5.0规范,深入讲解OSGi原理和服务,以及Equinox框架的用法和原理)', '周志明', 79.00, '机械工业出版社', '5F79D0D246AD4216AC04E9C5FAB3199E');
2. 项目搭建
1. 导入pom.xml
依赖的jar 表的插件
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.Mybatis-config.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>
<settings>
<!--SQL日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<environments default="development">
<environment id="development">
<!--事务管理器-->
<transactionManager type="JDBC"/>
<!--数据源-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/kdb2"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射代码存放区 -->
</configuration>
3. Mybatis 连接工具类
public class MyBatisUtil {
private static final String resource = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFactory;
static {
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// ThreadLocal是一个和线程相关的容器,只要是在同一个线程中,获取到的必定是同一个对象
private static ThreadLocal<SqlSession> TL = new ThreadLocal<>();
public static SqlSession openSession() {
SqlSession sqlSession = TL.get();
// 当前线程第一次调用该方法
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
TL.set(sqlSession);
}
return sqlSession;
}
public static void release(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.close();
}
}
}
4. log4j 配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
5.domain
public class Book {
private String bid;
private String bname;
private String author;
private Double price;
private String press;
private String cid;
// get/set method and toString
}
public class Category {
private String cid;
private String cname;
private String desc;
// get/set method and toString
}
1.关联查询的方式实现
1. 实体类 Book.java
2. 主配置文件 Mybatis-config.xml
</environments>
<mappers>
<mapper resource="cn/ccut/mapper/BookDao.xml" ></mapper>
</mappers>
3. 接口 IBookDao.java
public interface IBookDao {
List<Book> selectQuery();
}
4. BookDao.xml
<?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">
<!--namespace的值和接口全限定名一致的 -->
<mapper namespace="cn.ccut.dao.IBookDao">
<resultMap id="books" type="cn.ccut.domain.Book">
<id property="bid" column="bid"/>
<result property="bname" column="bname"/>
<result property="author" column="author"/>
<result property="price" column="price"/>
<result property="press" column="press"/>
<result property="cid" column="cid"/>
<!-- property 和数据库表中的属性一样,column book表中关联字段 -->
<association property="category" column="cid" javaType="cn.ccut.domain.Category">
<id property="cid" column="tcid"/>
<result property="cname" column="tcname"></result>
<result column="desc" property="desc"></result>
</association>
</resultMap>
<select id="selectQuery" resultMap="books">
select t1.cid tcid,t1.cname tcname,t1.desc,t.* from t_book t join t_category t1 on t.cid=t1.cid and t.cid="5F79D0D246AD4216AC04E9C5FAB3199E"
</select>
</mapper>
5. 测试
public class testS {
@Test
public void fun(){
IBookDao mapper = MyBatisUtil.openSession().getMapper(IBookDao.class);
System.out.println( mapper.selectQuery());
}
}
正确数据:
[Book{bid='52B0EDFF966E4A058BDA5B18EEC698C4', bname='亮剑Java Web项目开发案例导航(含DVD光盘1张)', author='朱雪琴', price=69.0, press='电子工业出版社', cid='5F79D0D246AD4216AC04E9C5FAB3199E', category=Category{cid='5F79D0D246AD4216AC04E9C5FAB3199E', cname='Java Javascript', desc='Java Javascript分类'}
2. 分步查询
1.domain 不变
2. BookDao.xml
<!--抽取-->
<mapper namespace="cn.ccut.dao.IBookDao">
<resultMap id="books01" type="cn.ccut.domain.Book">
<id property="bid" column="bid"/>
<result property="bname" column="bname"/>
<result property="author" column="author"/>
<result property="price" column="price"/>
<result property="press" column="press"/>
<result property="cid" column="cid"/>
</resultMap>
<resultMap id="books" extends="books01" type="cn.ccut.domain.Book">
<association property="category" column="cid" javaType="cn.ccut.domain.Category" select="typeQuery">
</association>
</resultMap>
<select id="selectQuery" resultMap="books">
select * from t_book
</select>
<select id="typeQuery" resultType="cn.ccut.domain.Category">
select * from t_category where cid=#{cid11111}
</select>
</mapper>
最简化版本
<?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="cn.ccut.dao.IBookDao">
<resultMap id="books" type="cn.ccut.domain.Book">
<association property="category" column="cid" javaType="cn.ccut.domain.Category" select="categoryQuery"/>
</resultMap>
<select id="selectQuery" resultMap="books">
select * from t_book
</select>
<select id="categoryQuery" resultType="cn.ccut.domain.Category">
select * from t_category where cid=#{cid11111}
</select>
</mapper>
3. XML文件的抽取 有利于复用
<?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="cn.ccut.dao.IBookDao">
<resultMap id="books01" type="cn.ccut.domain.Book">
<id property="bid" column="bid"/>
<result property="bname" column="bname"/>
<result property="author" column="author"/>
<result property="price" column="price"/>
<result property="press" column="press"/>
<result property="cid" column="cid"/>
</resultMap>
<resultMap id="books" extends="books01" type="cn.ccut.domain.Book">
<association property="category" column="cid" javaType="cn.ccut.domain.Category">
<id property="cid" column="tcid"/>
<result property="cname" column="tcname"></result>
<result column="desc" property="desc"></result>
</association>
</resultMap>
<select id="selectQuery" resultMap="books">
select t1.cid tcid,t1.cname tcname,t1.desc,t.* from t_book t join t_category t1 on t.cid=t1.cid and t.cid="5F79D0D246AD4216AC04E9C5FAB3199E"
</select>
</mapper>
不停的思考,就会不停的进步