Mybatis总结
Posted psxfd4
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis总结相关的知识,希望对你有一定的参考价值。
支持定制化 SQL、存储过程以及高级映射的优秀的数据库框架。
一、使用前准备
1.加入相关的jar包。这里使用mybatis-3.2.2.jar包,数据库使用mysql 5.5版本
2.创建mybatis的配置文件
这里创建一个demo,数据库名huayu,表有student,class,adviser,course,sc,teacher其结构分别为
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for adviser -- ---------------------------- DROP TABLE IF EXISTS `adviser`; CREATE TABLE `adviser` ( `aid` int(11) NOT NULL, `adviserName` varchar(10) DEFAULT NULL, PRIMARY KEY (`aid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for class -- ---------------------------- DROP TABLE IF EXISTS `class`; CREATE TABLE `class` ( `cid` int(11) NOT NULL, `method` varchar(20) DEFAULT NULL, `aid` int(11) DEFAULT NULL, PRIMARY KEY (`cid`), KEY `c_aid` (`aid`), CONSTRAINT `c_aid` FOREIGN KEY (`aid`) REFERENCES `adviser` (`aid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `cid` varchar(10) NOT NULL DEFAULT ‘‘, `cname` varchar(40) DEFAULT NULL, `coursehour` int(11) DEFAULT NULL, PRIMARY KEY (`cid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for sc -- ---------------------------- DROP TABLE IF EXISTS `sc`; CREATE TABLE `sc` ( `sid` int(11) NOT NULL DEFAULT ‘0‘, `cid` varchar(10) NOT NULL DEFAULT ‘‘, `score` int(11) DEFAULT NULL, `tid` int(11) DEFAULT NULL, PRIMARY KEY (`sid`,`cid`), KEY `t_tid` (`tid`), KEY `c_cid` (`cid`), CONSTRAINT `c_cid` FOREIGN KEY (`cid`) REFERENCES `course` (`cid`), CONSTRAINT `s_sid` FOREIGN KEY (`sid`) REFERENCES `student` (`sid`), CONSTRAINT `t_tid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`tid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `sid` int(11) NOT NULL, `sname` varchar(10) DEFAULT NULL, `age` int(11) DEFAULT NULL, `qualification` varchar(10) DEFAULT NULL, `cid` int(11) DEFAULT NULL, PRIMARY KEY (`sid`), KEY `s_cid` (`cid`), CONSTRAINT `s_cid` FOREIGN KEY (`cid`) REFERENCES `class` (`cid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` ( `tid` int(11) NOT NULL, `tname` varchar(10) DEFAULT NULL, PRIMARY KEY (`tid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
结构模型图
配置文件,Mybatis优化:使用属性文件;
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/huayu
username=root
password=root
<?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="db.properties" />
<!--此处为配置分页查询PageHelper的代码 -->
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- config params as the following --> <property name="param1" value="value1" /> </plugin> </plugins> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <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> </mappers> </configuration>
3.创建映射文件,映射文件相当于dao接口的实现类,首先创建StudentMapper,写一个方法queryByCidAndQua,根据班级号和学历查询
<?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.zhiyou100.cyf.dao.StudentMapper"> <sql id="all_cols"> sid,sname,age,qualification,cid </sql> <select id="queryByCidAndQua" resultType="com.zhiyou100.cyf.bean.Student"> select <include refid="all_cols"></include> from student where cid=#cid and qualification=#qua </select> </mapper>
优化:要传递的参数为两个以上时,框架会默认将其放进一个map内,key值分别为0,1或param1,param2,value为参数值,在接口的方法设置注解改变默认key
List<Student> queryByCidAndQua(@Param("qua")String qua,@Param("cid")String cid);
4.映射文件要引入到配置文件内
在configuration标签内添加
<mappers> <mapper resource="com/zhiyou100/cyf/mapper/StudentMapper.xml" /> </mappers>
5.加入日志:引入log4j-1.2.17.jar包,创建日志文件log4j.properties
log4j.properties,
log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
二、创建关系表和对应的实体类、操作接口和实现的映射文件
1.dao接口结合对应的映射文件
映射文件的namespace属性应为该接口的位置,接口的方法名与映射文件中相应的id属性值相同,再建一个ClassMapper映射,将列名改动一下method -> c_method,在问题sql字段与java属性不匹配里解决。
List<Class> selectAll();//接口中暂加一个方法
三、测试
class StudentMapperTest static SqlSession session=null; static StudentMapper sm=null; @BeforeAll static void setUpBeforeClass() throws Exception Reader reader=Resources.getResourceAsReader("conf.xml"); SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader); session=sessionFactory.openSession(); sm=session.getMapper(StudentMapper.class); @AfterAll static void tearDownAfterClass() throws Exception session.commit(); @Test void testQueryByCidAndQua() List<Student> list=sm.queryByCidAndQua("本科", "20100101");//两个参数。可以用map传,不过这样写框架会默认创建map System.out.println(list);
四、一些问题
1.sql字段与java属性不匹配
一种方案是给查询字段起别名,使其与java属性一致
另一种是使用resultMap标签来定义实体类与字段之间的对应关系
<mapper namespace="com.zhiyou100.cyf.dao.ClassMapper"> <sql id="all_cols"> cid,c_method,aid </sql> <select id="selectAll" resultMap="classMap"> select <include refid="all_cols"/> from class </select> <resultMap type="com.zhiyou100.cyf.bean.Class" id="classMap"> <result column="c_method" property="method"/> </resultMap> </mapper>
2.连表查询
一对一或多对一:一个班有一个老师,根据班级id查询所关联的老师信息,或根据班级内的学生查询所关联的老师信息
在班级类中增加一个老师的属性
<resultMap type="com.zhiyou100.xz.bean.Clazz" id="clazzMapper"> <!-- id:标签标识表中的主键与实体类的值属性对应关系 --> <id column="c_id" property="cid"/> <result column="c_name" property="cname"/> <result column="teacher_id" property="tid"/> <!-- 该类中引入的一的一方的属性 property:属性名 javaType:该属性的Java类型 --> <association property="teacher" javaType="com.zhiyou100.cyf.bean.Teacher"> <id column="t_id" property="tid"/> <result column="t_name" property="tname"/> </association>
select中语句为连接查询语句。如果用嵌套查询,则需要另外创建并实现TeacherDao的queryById方法
<association property="teacher" javaType="com.zhiyou100.xz.bean.Teacher" column="teacher_id" select="com.zhiyou100.cyf.dao.TeacherDao.queryById"> </association>
一对多:如查询在一个班的所有学生
在班级类内创建students属性,类型为List<Student>
</association> <!-- ofType:集合中泛型的类型 --> <collection property="students" ofType="com.zhiyou100.cyf.bean.Student"> <id property="sid" column="s_id"/> <result property="sname" column="s_name"/> </collection>
在resultMap中添加collection标签,mybatis会自动给若干个student装进一个集合。同样,如果用嵌套查询,要在StudentDao中创建并实现返回list的queryByCId方法
<collection property="students" ofType="com.zhiyou100.cyf.bean.Student" column="c_id" select="com.zhiyou100.cyf.dao.StudentDao.queryByCId"></collection>
3.sql语句中$与#区别:
$: 解析时不会为内容添加””,他是sql语句的拼接存在sql注入的危害。传入的为表结构,order by排序等不需要字符串的情况下使用它。
#: 解析时会为内容添加””,它的sql时采用占位符,防止sql注入,尽量使用。
4.添加对象时如何把生产的id返回
<insert parameterType="com.zhiyou100.cyf.bean.User" userGenerateKeys="true" keyProperty="id">insert user(name,age) values(#name,#age)</insert>
userGenerateKeys,keyProperty两个属性必须同时使用,id返回到调用者的参数user对象的id属性上
5.测试类中update类操作的事务性
@AfterAll
static void tearDownAfterClass() throws Exception
session.commit();//在代码执行完后,才使数据库执行增删改操作
为了保证安全和严谨,此处模拟了事务操作,一系列操作要么都执行,要么都不执行
以上是关于Mybatis总结的主要内容,如果未能解决你的问题,请参考以下文章