Mybatis总结
一, 安装
基于Maven来构建项目,需要将mybatis
包导入pom.xml
文件中,(我的数据库基于mysql
,所以也将它一起导入), 如下:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<!--当然版本号自选-->
需要在pom.xml的下面,将两个文件夹下的 ..xml 文件加入编译,如下:
<build>
<finalName>Mybatis_001</finalName>
<!--将两个文件夹下的 .xml ...加入编译-->
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.tld</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.tld</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
二, resources的配置
可以创建一个
db.properties 进行动态替换
当有不同的数据库需要创建连接时,不需要更改大量的代码,只要添加一条 url(如下: jdbc2.url), 将 env_choosen 改为与 confing.xml 中 environment id="xxx" 的 xxx 相对应,
jdbc.driver=com.mysql.jdbc.Driver jdbc1.url=jdbc:mysql://localhost:3306/数据库1 jdbc.username=xxx jdbc.password=xxx env_choosen=deve1 jdbc2.url=jdbc:mysql://localhost:3306/数据库2
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> <!--这个配置文件中,所有的标签都有严格的顺序--> <!--引入数据库连接配置文件--> <properties resource="db.properties"/> <!--别名--> <typeAliases> <!--指定别名--> <!--<typeAlias type="com.stu.bean.Student" alias="Student"/>--> <!--不指定 类名即别名--> <package name="com.stu.bean"/> </typeAliases> <!--根据db.properties 中的 env_choosen 指向数据库连接--> <environments default="${env_choosen}"> <environment id="deve1"> <!--固定JDBC--> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <!--数据库连接条件--> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc1.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> <environment id="deve2"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <!--数据库连接条件--> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc2.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <!--对应 mapper 包下的 .xml文件--> <!--<mapper resource="com/stu/mapper/StudentMapper.xml"/>--> <!--自动读取mapper包下的所有xml文件--> <package name="com.stu.mapper"/> </mappers> </configuration>
mapper包下
接口中定义的方法,与xml中产生映射关系
public interface StudentMapper { //查询所有学生 List<Student> findAllStudent(); //如果参数有多个,使用@Param注解规定参数的别名 void insertStudent(@Param("sname") String name); void insertStu(Student student); }
映射文件
<?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="com.stu.mapper.StudentMapper"> <!--mybatis 的结果映射 如果当实体类的属性名和数据库表的列名不一致的情况下,需要使用结果映射来确保数据的一致性--> <!--结果映射写在最上方--> <!--在config.xml未定义别名的情况下,type为全路径,定义别名的情况下,直接写类名即可--> <resultMap id="BaseMap" type="com.stu.bean.Student"> <!--column数据库表的列名 property 实体类的属性名--> <id column="id" property="id"/> <result column="name" property="name"/> </resultMap> <!--保存一段sql片段,以供反复使用--> <sql id="Column_List"> id,name </sql> <select id="findAllStudent" resultMap="BaseMap"> SELECT <include refid="Column_List"/> FROM student </select> <!--sname 与接口方法中参数相对应--> <insert id="insertStudent"> INSERT INTO student VALUES (NULL ,#{sname}) -- # 可以防止sql注入 -- INSERT INTO student VALUES (NULL ,'${sname}') -- $ 不安全,不能防止sql注入 </insert> <!--使用条件: 添加对象的情况下,mysql环境下,可以得到完整的对象属性--> <insert id="insertStu" useGeneratedKeys="true" keyProperty="id" parameterType="com.lanou.bean.Student"> INSERT INTO student VALUES (NULL ,#{name}) </insert> </mapper>
三. 测试类
public void test1() throws IOException {
//以下 1~4 都是重复代码,可以封装成 util 方便调用
//1,加载config文件
String re = "config.xml";
InputStream inputStream = Resources.getResourceAsStream(re);
//2,创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//3,生产sqlSession对象
SqlSession session = factory.openSession();
//4,获取mapper对象
StudentMapper mapper = session.getMapper(StudentMapper.class);
//5,调用方法获取结果
Student student = new Student();
student.setName("张三");
mapper.insertStu(student);
//对数据库进行修改,需要使用session提交事务
session.commit();
session.close();
}
四. 表之间关联关系
在resultMap
中进行配置
一对一
<resultMap id="BaseMap" type="Xxx"> <id column="id" property="id"/> <result column="name" property="name"/> <!-- 一对一 propertype为实体类中相对应 --> <association property="stu" column="stu_id" javaType="Student" select="com.stu.mapper.StudentMapper.findStuById"/> </resultMap>
一对多
<resultMap id="BaseMap" type="Class"> <id column="id" property="id"/> <result column="name" property="name"/> <!-- 一对多 --> <!--返回多个对象,用ArrayList--> <collection property="stuList" column="stu_id" javaType="ArrayList" select="com.stu.mapper.StudentMapper.findStuById"/> </resultMap>
- ####多对多
多对多与一对多相似,就是各在两个接口映射文件中的resultMap中进行配置,但应注意的是:每个映射文件中应保留一个纯净的resultMap (未加<collection/>) 否则会发生递归(死循环)
五. 动态sql
if 用来进行条件判断
<select id="findAllBlog" resultMap="BaseMap"> SELECT <include refid="Column_List"/> FROM blog WHERE state = 'active' <if test="btitle != null"> AND title = #{btitle} </if> <if test="bauthor != null"> AND author =#{bauthor} </if> </select>
choose 相当于
switch case
<select id="findBlogs" resultMap="BaseMap"> SELECT <include refid="Column_List"/> FROM blog WHERE state = 'active' <choose> <when test="title != null"> AND title = #{title} </when> <when test="content != null"> AND content = #{content} </when> <otherwise> AND id = 1 </otherwise> </choose> </select>
where 用于任何需要使用’where’的地方,取代where的sql语句,会自动调整内部的条件语法,剪掉开头的and或者or语句
<select id="findBlogsWithWhere" resultMap="BaseMap"> SELECT <include refid="Column_List"/> FROM blog <where> <if test="state != null"> AND state = #{state} </if> <if test="title != null"> AND title = #{title} </if> </where> </select>
set 一般用于update 用于替代set语句,将条件列表的最后的逗号剪掉
<update id="updateBlog"> UPDATE blog <set> <if test="title != null"> title = #{title}, </if> <if test="content != null"> content = #{content}, </if> </set> WHERE id = #{id} </update>
trim 是where和set的实现机制
<!--prefix:整体sql的内容的前缀 suffix:整体sql的内容的后缀 <!--prefixOverride: 需要剪掉的前缀内容 suffixOverride: 需要剪掉的后缀内容--> <insert id="insertBlog"> INSERT INTO blog <trim prefix="(" suffix=")" suffixOverrides=","> <if test="title != null"> title, </if> <if test="content != null"> content, </if> </trim> <trim prefix="values(" suffix=")" suffixOverrides=","> <if test="title != null"> #{title}, </if> <if test="content != null"> #{content}, </if> </trim> </insert>
foreach 通常与where搭配,用在in中
<select id="findBlogsWithIds" resultMap="BaseMap"> SELECT <include refid="Column_List"/> FROM blog WHERE id IN <foreach collection="ids" item="item" index="index" open="(" separator="," close=")"> #{item} </foreach> </select>