详细的Mybatis介绍/使用,可以访问:
地址:mybatis – MyBatis 3 | 简介
目录
一、Mybatis介绍
二、依赖
三、什么是rowmapper
四、Mybatis demo 演示
4.1 背景
4.2 JDBC执行sql的流程 &Mybatis 关键要素
4.3 项目的整体结构:
4.4 Mybatis XML简单配置
4.5 数据库表及对应的实体类
4.6 mapper(封装sql)
4.7 运行入口
五、Mybatis 总配置
5.1 多数据库配置
5.2 数据库表中的字段与自定义类的属性对应关系。
5.3 xml配置文件,使用变量properties
六、sql注解版 mapper
七、xml 配置 mapper ,增删改查
7.1 xml 配置 mapper ,中sql 参数传递&查
7.1.1 通过变量传递sql参数&查
7.1.2 通过对象传递sql参数
7.2 增删改
八、注解版mapper ,增删改查
九、获取自增主键的值
9.1 注解mapper ,获取自增主键的值
9.2 xml mapper ,获取自增主键的值
十、动态sql
10.1 背景
10.2 xml mapper动态sql
10.3 注解版mapper 动态sql
十一、批量插入
11.1 xml 批量插入
11.2 sql注解批量插入
十二、批量删除
12.1 xml 批量删除
12.2 sql注解删除
一、Mybatis介绍
MyBatis 可能是当前互联网公司数据库持久层框架的首页。为啥?因为Mybatis比JDBC方便。
1、MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
2、MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
二、依赖
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
三、什么是rowmapper
这里强行插一下rowmapper的解释,因为我总是忘了它是干嘛的。
row,行。数据库的中一行数据,也就是一条数据。
mapper,映射。将一条数据,组装成一个实体类。
我们在执行查询sql的时候,返回结果是以什么形式存在的呢?我们将返回结果组装成了我们自定义类的实例。
rowmapper里面,就是写的我们具体组装的逻辑。如下
List<TbUser> tbUsers1 = testRowMapper(sql, null, new RowMapper<TbUser>() {
// 重写map
@Override
public TbUser map(ResultSet rs) throws SQLException {
TbUser tbUser = new TbUser();
// 给tbUser赋值
tbUser.setId(rs.getLong(1));
tbUser.setName(rs.getString(2));
return tbUser;
}
});
传参中,需要传一个rowmapper,mapper就是我们具体将一条数据封装到我们自定义类里的详细逻辑。(我们将返回结果/一条数据,)组装到了我们自定义类里。
return的时候,不是return的一大堆字符串,而是一个对象。
四、Mybatis demo 演示
4.1 背景
表MyStudent
CREATE TABLE `MyStudent` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=201200000 DEFAULT CHARSET=utf8;
在表里插入数据
insert into MyStudent values(201215121,'李勇',20),(201215122,'刘晨',19),(201215123,'王敏',18);
执行查询SQL,select * from MyStudent,收集查询结果。
4.2 JDBC执行sql的流程 &Mybatis 关键要素
当我们使用jdbc 执行sql时,流程是这样的
1、配置数据库的相关信息(url、username、password)等
2、与数据库建立连接
3、执行sql
4、将执行sql的返回结果进行封装,返回。
使用 Mybatis 执行sql,这几个关键步骤都是要有的,但是具体形式是不一样的。
1、XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源
2、mapper,这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。(啥是映射?就是将sql执行后,得到的数据,组装成我们自定义的类的实例)。
我对mapper的理解,就是1、封装要执行的sql 2、将封装好的sql与mapper的类的方法做关联。
当具体要执行sql的时候,我们调用mapper的某个方法,这个方法的本质就是去调用了我们封装的sql。
4.3 项目的整体结构:
4.4 Mybatis XML简单配置
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。后面会再探讨 XML 配置文件的详细内容,这里先给出一个简单的示例:
xml模版:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<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>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
手动将模版中数据库相关信息,替换成自己的数据库信息。我们需要修改2个点。
1、其中<dataSource type="POOLED"> 内,配置的是数据库连接信息。
2、<mappers> mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。(啥是映射?就是将sql执行后,得到的数据,组装成我们自定义的类的实例)
在resources文件夹下,新建mytatis-config.xml文件。配置我们自己的相关信息。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://124.70.87.136/chen?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="$123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
注意:我们在写url时,url中符号&在xml文件中,需要转义,使用&
如原来url
jdbc:mysql://124.70.87.16/chen?useUnicode=true&characterEncoding=UTF-8
转义后:
jdbc:mysql://124.70.87.16/chen?useUnicode=true&characterEncoding=UTF-8
4.5 数据库表及对应的实体类
在我们的项目代码中,要有一个对应的类。MyStudent类
设置无参构造器、所有参数的构造器
package beans;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyStudent {
private long id;
private String name;
private int age;
public MyStudent(String name, int age) {
this.name = name;
this.age = age;
}
}
4.6 mapper(封装sql)
<mappers> mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。(啥是映射?就是将sql执行后,得到的数据,组装成我们自定义的类的实例)
我对mapper的理解,就是1、封装要执行的sql 2、将封装好的sql与mapper的类的方法做关联。
当具体要执行sql的时候,我们调用mapper的某个方法,这个方法的本质就是去调用了我们封装的sql。
我们执行的是select * 的sql语句,返回结果是一个list。
编写mapper接口----MyStudentMapper(里面就是将sql封装成了方法)
package mapper;
import beans.MyStudent;
import java.util.List;
public interface MyStudentMapper {
List<MyStudent> findAll();
MyStudent findById(long id);
}
然后在MyStudentMapper.xml中,配置MyStudentMapper接口中的sql相关信息。
MyStudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 与mapper接口的全类名保持一致-->
<mapper namespace="mapper.MyStudentMapper">
<!--id要和mapper接口的方法名保持一致 -->
<!-- resultType 与sql返回值对应的类的全类名保持一致-->
<select id="findAll" resultType="beans.MyStudent">
select * from MyStudent
</select>
<select id="findById" resultType="beans.MyStudent">
select * from MyStudent where id = #{id}
</select>
</mapper>
解释:
1、namespace 与mapper接口的全类名保持一致。这样将来调用mapper类方法的时候,才能找我我们这个映射
2、id要和mapper接口的方法名保持一致,这样将来调用mapper类方法的时候,才能找我我们这个方法
3、resultType 与sql返回值对应的类的全类名保持一致。这样才能将返回结果组装成我们自定义的实体类。(这里是通过反射实现的,通过类名,得到实例)
4、里面有具体的sql语句。select * from MyStudent
5、sql中的参数传递,使用#{xx}
4.7 运行入口
app
package main;
import beans.MyStudent;
import mapper.MyStudentMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class App {
public static void main(String[] args) throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 选择不同的数据库,指定数据库
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
// 得到MyStudent表的mapper
MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
// 调用mapper的方法
List<MyStudent> all = myStudentMapper.findAll();
System.out.println("all = " + all);
MyStudent byId = myStudentMapper.findById(201215121);
System.out.println("byId = " + byId);
sqlSession.close();
}
}
解释:
1、连接数据库,建立连接。(读取数据库配置文件,然后建立连接)
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 选择不同的数据库,指定数据库
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
2、(通过mapper)执行sql
// 得到MyStudent表的mapper
MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
// 调用mapper的方法
List<MyStudent> all = myStudentMapper.findAll();
3、关闭连接,千万别忘了关闭连接
sqlSession.close();
五、Mybatis 总配置
我们接着第四节讲。
5.1 多数据库配置
数据库连接,在mybatis-config.xml中,进行配置。
1、修改默认库
同一个库,有一个开发库,一个测试库。如下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 开启自动驼峰命名-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://124.70.87.136/chen?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://124.70.87.136/chen?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/MyStudentMapper.xml"/>
</mappers>
</configuration>
id就是数据库的名字,
<environments default="development">
设置,默认使用的数据库。可以更换成test库。
则我们在生成SqlSessionFactory的时候,生成的就是我们默认的那个数据库。
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 选择不同的数据库,指定数据库
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
2、在生成SqlSessionFactory的时候,指定对应的数据库
我们不同的业务模块,连接的是不同的数据库。在生成SqlSessionFactory的时候,指定对应的数据库id。
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 选择不同的数据库,指定数据库
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
5.2 数据库表中的字段与自定义类的属性对应关系。
在第四节中,数据库的表。
数据库中的列名,与我们的自定义类属性名,一摸一样。这样框架就会自动的把数据给我们组装成一个实体类。
那我们表的列名与类的属性名称不一致,咋整?
情况一:开启驼峰命名自动映射
数据库命名与java命名规范是不一致的。
如,Your Student表,列名为下划线,user_id
但是依照我们java命名规范,对应的实体类属性为驼峰格式,userId,userName。
package beans;
import lombok.Data;
@Data
public class YourStudent {
private long userId;
private String userName;
private int userAge;
}
两边列名是不一致的。我们可以在Mybatis的总配置文件mybatis-config.xml中,开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 |
在mybatis-config.xml中,配置setting模块就好。
情况二:表的列名与自定义类的属性名称不一致,且也不是驼峰映射的情况。
如表中的列名,id 对应 类中的myId,name对应类中的designation。
我们需要手动的,去写列名与类属性名的一一对应关系。应该去哪里写呢?
正常情况下,这个映射实在row mapper里完成的。mybatis里的mapper,是一个xml配置文件。
我们需要去MyStudentMapper.xml 中配置。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.YourStudentMapper">
<resultMap id="yourStudent" type="beans.YourStudent">
<id column="id" property="myId"/>
<result column="name" property="designation"/>
<result column="age" property="year"/>
</resultMap>
<select id="findAll" resultMap ="yourStudent">
select * from MyStudent
</select>
</mapper>
在resultMap中,编写列名与属性名的映射关系。
<resultMap id,这里的id是这个Map的名称,可以随意命名。
type=,写的对应的实体类的全类名
<id /> <result /> 中,写的具体映射关系,column表的列名,property实体类的属性名。
<id /> 表的主键,<result /> 表中普通的列。
注意,写完Map后,写到sql语句的resultMap上。注意(这里是resultMap,不是resultType=)
5.3 xml配置文件,使用变量properties
方式一:在xml中设置变量property (这种方式不常用。)
在 <properties> 中,设置变量,引用变量时,${xxx}
方式二:在xml配置文件中,引入数据库配置文件
我们习惯性的将数据库配置mysql.properties中。
mysql.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://124.70.87.136/chen?useUnicode=true&characterEncoding=UTF-8
userName=root
password=123456
然后在mybatis-config.xml配置文件中,引入mysql.properties。
然后设置变量。
六、sql注解版 mapper
以上,我们讲的使用mapper来构造执行sql语句的方法,由2部分组成。
1部分是接口,里面有用户行为的方法
2部分就是xml的mapper配置文件,里面写了具体执行的sql,以及对应的类,类的方法,返回数据类型。
然后在mybatis主配置文件mybatis-config.xml中,mappers模块下,配置这个我们mapper xml文件的路径。
mapper注解版,就是讲1与2,合二为一。我们在接口的方法中,通过注解,来写对应的sql。
举例,上面那个查询全部的行为。
package mapper;
import beans.MyStudent;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface MyStudentMapper {
@Select("select * from MyStudent")
List<MyStudent> findAll();
}
我们只需要在mapper接口,对应的行为上,注解对应的sql语句就可以了。
这样,类方法与sql对应的关系、sql返回的数据类型,框架都可以识别到,不需要我们再去xml文件中配置了。
然后我们再修改mybatis主配置文件mybatis-config.xml中,mappers模块下,将原来的resource=xml的路径,改成class = 接口的全类名,这样我们就可以找到对应的接口了。
当我们使用xml 配置mapper 时,有多个xml文件时,需要配置多个xml文件。
当我们使用注解接口时,有多个接口,也要分别写多个接口的class。
<mapper class="mapper.MyStudentMapper" />
我们还可以写这些接口所在的包,框架会去扫描包下所有的接口。
<package name="mapper"/>
<mappers>
<!--<mapper resource="mapper/MyStudentMapper.xml"/> -->
<!--<mapper class="mapper.MyStudentMapper" /> -->
<package name="mapper"/>
</mappers>
项目结构:
七、xml 配置 mapper ,增删改查
7.1 xml 配置 mapper ,中sql 参数传递&查
7.1.1 通过变量传递sql参数&查
1、在接口,有三个方法,分别需要传0个,1个,2个参数。
package mapper;
import beans.MyStudent;
import java.util.List;
public interface MyStudentMapper {
List<MyStudent> findAll();
MyStudent findById(long id);
MyStudent findByName(String name,int age);
}
2、对应的xml配置,sql 参数
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 与mapper接口的全类名保持一致-->
<mapper namespace="mapper.MyStudentMapper">
<!--id要和mapper接口的方法名保持一致 -->
<!-- resultType 与sql返回值对应的类的全类名保持一致-->
<select id="findAll" resultType="beans.MyStudent">
select * from MyStudent
</select>
<select id="findById" resultType="beans.MyStudent">
select * from MyStudent where id = #{id}
</select>
<select id="findByName" resultType="beans.MyStudent">
select * from MyStudent where name = #{name} and age = #{age}
</select>
</mapper>
规则:
1、方法中,只需要一个参数时,sql语句中的变量名,可以任意命名。
如 id= #{id},可以任意命名 id= #{abcd},
2、方法中,需要多个参数时,sql语句中的变量名,需要与方法中的变量名保持一致。
如在方法中,
MyStudent findByName(String name,int age);
则sql语句中的变量就要为 #{name} #{age}
select * from MyStudent where name = #{name} and age = #{age}
如果想要sql语句中的变量,与方法中的变量名称不一致,我们需要在方法中使用@Parm注解,来指定sql中的变量名称。
如
public interface MyStudentMapper {
List<MyStudent> findAll();
MyStudent findById(long id);
MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);
}
方法中的变量name 对应sql中的myName变量
<select id="findByName" resultType="beans.MyStudent">
select * from MyStudent where name = #{myName} and age = #{myAge}
</select>
7.1.2 通过对象传递sql参数
sql中,我们需要传递多个参数。我们可以new一个对象,然后传递这个对象。
接口的方法,传参为一个对象
具体的sql语句中,还是一个个变量,系统会去我们传递的对象中,找对应的属性,来填充sql中的变量。
举例:
MyStudent实体类,有三个属性,我们根据name、age这两个属性去做查询。
先改造MyStudent,给它一个无参构造器和name、age这两个属性的构造器。
package beans;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class MyStudent {
private long id;
private String name;
private int age;
public MyStudent(String name, int age) {
this.name = name;
this.age = age;
}
}
然后在接口中,新增一个传参为MyStudent实体类的方法。
MyStudent findByObject(MyStudent myStudent);
public interface MyStudentMapper {
List<MyStudent> findAll();
MyStudent findById(long id);
MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);
MyStudent findByObject(MyStudent myStudent);
}
在mapper xml中配置这个方法
<select id="findByObject" resultType="beans.MyStudent" parameterType="beans.MyStudent">
select * from MyStudent where name = #{name} and age = #{age}
</select>
parameterType="beans.MyStudent" ,传参对象的类型
name = #{name} and age = #{age},#{name} 会去对象中,匹配属性。
方法使用,我们在调用这个方法时,直接传一个对象就好了。
MyStudent byObject = myStudentMapper.findByObject(new MyStudent("王敏", 18));
System.out.println("byObject = " + byObject);
7.2 增删改
接口
package mapper;
import beans.MyStudent;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MyStudentMapper {
List<MyStudent> findAll();
MyStudent findById(long id);
MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);
MyStudent findByObject(MyStudent myStudent);
// 增
int add(MyStudent myStudent);
// 改
int update(MyStudent myStudent);
// 删除
int delete(long id);
}
mapper xml 配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 与mapper接口的全类名保持一致-->
<mapper namespace="mapper.MyStudentMapper">
<!--id要和mapper接口的方法名保持一致 -->
<!-- resultType 与sql返回值对应的类的全类名保持一致-->
<select id="findAll" resultType="beans.MyStudent">
select * from MyStudent
</select>
<select id="findById" resultType="beans.MyStudent">
select * from MyStudent where id = #{id}
</select>
<select id="findByName" resultType="beans.MyStudent">
select * from MyStudent where name = #{myName} and age = #{myAge}
</select>
<select id="findByObject" resultType="beans.MyStudent" parameterType="beans.MyStudent">
select * from MyStudent where name = #{name} and age = #{age}
</select>
<insert id="add" parameterType="beans.MyStudent">
insert into MyStudent (name,age) values (#{name},#{age})
</insert>
<update id="update" parameterType="beans.MyStudent">
update MyStudent set name = #{name},age = #{age} where id = #{id}
</update>
<delete id="delete">
delete from MyStudent where id = #{id}
</delete>
</mapper>
add 方法为增
update 方法为改
delete 方法为删
注意:
1、在xml配置文件中,我们的增 与 改,传参都是对象。需要设置对象类型parameterType="beans.MyStudent"
删,是根据long类型的id,进行删除的,传参为基本类型时,不需要设置传参的类型
2、delete 删除,我们很少使用,一般是逻辑删除。
方法的调用
package main;
import beans.MyStudent;
import mapper.MyStudentMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class App {
public static void main(String[] args) throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 选择不同的数据库,指定数据库
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"development");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 得到MyStudent表的mapper
MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
// 调用mapper的方法
MyStudent byId = myStudentMapper.findById(201215121);
System.out.println("byId = " + byId);
MyStudent byName = myStudentMapper.findByName("王敏", 18);
System.out.println("byName = " + byName);
MyStudent byObject = myStudentMapper.findByObject(new MyStudent("王敏", 18));
System.out.println("byObject = " + byObject);
int i = myStudentMapper.add(new MyStudent("张三", 19));
System.out.println("i = " + i);
int update = myStudentMapper.update(new MyStudent(201215125, "李四", 19));
System.out.println("update = " + update);
int delete = myStudentMapper.delete(201215125);
System.out.println("delete = " + delete);
// sqlSession.commit();
sqlSession.close();
}
}
1、增、删、改行为,执行sql,都需要提交事物。
方法一,在创建sqlSession 时,添加true,开启自动提交事物
SqlSession sqlSession = sqlSessionFactory.openSession(true);
方法二,我们在执行sql后,手动提交事物。
int delete = myStudentMapper.delete(201215125);
System.out.println("delete = " + delete);
sqlSession.commit();
八、注解版mapper ,增删改查
mapper接口,MyStudentMapper,方法与sql写一起
package mapper;
import beans.MyStudent;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface MyStudentMapper {
@Select("select * from MyStudent")
List<MyStudent> findAll();
@Select("select * from MyStudent where id = #{id}")
MyStudent findById(long id);
@Select("select * from MyStudent where name = #{myName} and age = #{myAge}")
MyStudent findByName(@Param("myName") String name, @Param("myAge") int age);
@Select("select * from MyStudent where name = #{name} and age = #{age}")
MyStudent findByObject(MyStudent myStudent);
// 增
@Insert("insert into MyStudent (name,age) values (#{name},#{age})")
int add(MyStudent myStudent);
// 改
@Update("update MyStudent set name = #{name},age = #{age} where id = #{id}")
int update(MyStudent myStudent);
// 删除
@Delete("delete from MyStudent where id = #{id}")
int delete(long id);
}
方法调用
package main;
import beans.MyStudent;
import mapper.MyStudentMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class App {
public static void main(String[] args) throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 选择不同的数据库,指定数据库
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in,"test");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 得到MyStudent表的mapper
MyStudentMapper myStudentMapper = sqlSession.getMapper(MyStudentMapper.class);
// 调用mapper的方法
List<MyStudent> all = myStudentMapper.findAll();
System.out.println("all = " + all);
// 调用mapper的方法
MyStudent byId = myStudentMapper.findById(201215121);
System.out.println("byId = " + byId);
MyStudent byName = myStudentMapper.findByName("王敏", 18);
System.out.println("byName = " + byName);
MyStudent byObject = myStudentMapper.findByObject(new MyStudent("王敏", 18));
System.out.println("byObject = " + byObject);
int i = myStudentMapper.add(new MyStudent("张三", 19));
System.out.println("i = " + i);
int update = myStudentMapper.update(new MyStudent(201215126, "李四", 19));
System.out.println("update = " + update);
int delete = myStudentMapper.delete(201215126);
System.out.println("delete = " + delete);
sqlSession.close();
}
}
九、获取自增主键的值
背景:
表MyStudent,id是自增主键。
当我们插入数据时,(一共3个字段),name与age是我们手动插入的,id是系统自动生成的。
我们如何取到系统生成的id的值呢?
insert into MyStudent (name,age) values (#{name},#{age}
9.1 注解mapper ,获取自增主键的值
接口配置
// 增
@Insert("insert into MyStudent (name,age) values (#{name},#{age})")
@Options(useGeneratedKeys = true,keyProperty = "id")
int add(MyStudent myStudent);
使用注解@Options。keyProperty="id",MyStudent 实体类中的属性值。
调用:
MyStudent myStudent = new MyStudent("张三", 19);
int i = myStudentMapper.add(myStudent);
System.out.println("i = " + i);
System.out.println("myStudent = " + myStudent);
9.2 xml mapper ,获取自增主键的值
xml mapper配置文件
<insert id="add" parameterType="beans.MyStudent" useGeneratedKeys="true" keyProperty="id">
insert into MyStudent (name,age) values (#{name},#{age})
</insert>
useGeneratedKeys="true" keyProperty="id"
keyProperty="id",MyStudent 实体类中的属性值。
调用
MyStudent myStudent = new MyStudent("张三", 19);
int i = myStudentMapper.add(myStudent);
System.out.println("i = " + i);
System.out.println("myStudent = " + myStudent);
十、动态sql
10.1 背景
动态sql,就是给sql赋予一段处理逻辑。
如我们原来的sql
select * from MyStudent where name = #{name} and age = #{age}
根据name and age 去做查询。当我们只需要一个条件name或者age去查询的时候如何做处理?
没有必要再写一个新的sql,我们给它加一段逻辑。当name与age 都不为空时,用这两个条件去查询。当有一个条件为空时,用另一个条件去查询。
10.2 xml mapper动态sql
方式一:
修改mapper xml sql语句,使用<where>
<select id="findByList" resultType="beans.MyStudent" parameterType="beans.MyStudent">
select * from MyStudent
<where>
<if test="name != null">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</select>
注意,这里每个条件前边,都加了一个and。
为啥要加and? 因为当我们多个条件同时查询时,需要用and连接。 这个<where> 应该是对只用一个条件查询时,做了特殊处理,比如方式二,用了1=1做了处理。
方式二:
修改mapper xml sql语句,使用1=1
<select id="findByList" resultType="beans.MyStudent" parameterType="beans.MyStudent">
select * from MyStudent where 1=1
<if test="name != null">
and name = #{name}
</if>
<if test="age != null">
and age = #{age}
</if>
</select>
注意,这里每个条件前边,都加了一个and。
为啥要加and? 因为当我们多个条件同时查询时,需要用and连接。
为啥要加1=1?因为当我们只用一个条件查询时,sql就变成了这样
select * from MyStudent where and name = #{name}
条件里,多了一个and,我们在前边加一个1=1,sql就变成了正常sql了。
select * from MyStudent where 1=1 and name = #{name}
10.3 注解版mapper 动态sql
修改,接口方法上的sql注解。
@Select("<script> select * from MyStudent\n" +
" <where>\n" +
" <if test=\"name != null\">\n" +
" and name = #{name}\n" +
" </if>\n" +
" <if test=\"age != null\">\n" +
" and age = #{age}\n" +
" </if>\n" +
" </where></script>")
List<MyStudent> findByList(MyStudent myStudent);
有个简便的方法,就是我们先在xml里写好了sql,在复制到这个接口上。
复制这个:
然后粘贴到 接口的注解上
注意,这里多了一个<script></script>
十一、批量插入
11.1 xml 批量插入
在接口中,增加批量插入的方法
// 批量插入
int insertAll(List<MyStudent> list);
修改xml文件
<insert id="insertAll" parameterType="beans.MyStudent">
insert into MyStudent (name,age) values
<foreach collection="list" separator="," item="item">
(#{item.name},#{item.age})
</foreach>
</insert>
解释:
正常情况下,批量插入的sql语句,格式为
insert into MyStudent (name,age) values (name1,age1),(name2,age2),(name3,age3)
我们这里也是使用函数,来拼成这个格式。
collection="list",我们传入的是一个list集合,List<MyStudent>
separator="," 我们sql中,多个元素之间,使用逗号进行分割的
item="xx", xx指代集合中的每一个元素。
#{item.name} 集合中,每个元素的name值
调用:
ArrayList<MyStudent> students = Lists.newArrayList(new MyStudent("张三三", 19), new MyStudent("李思思", 19));
int all = myStudentMapper.insertAll(students);
System.out.println("all = " + all);
11.2 sql注解批量插入
在接口中,增加批量插入的方法
// 批量插入
int insertAll(List<MyStudent> list);
给方法增加sql注解
// 批量插入
@Insert("<script> insert into MyStudent (name,age) values\n" +
" <foreach collection=\"list\" separator=\",\" item=\"item\">\n" +
" (#{item.name},#{item.age})\n" +
" </foreach> </script>")
int insertAll(List<MyStudent> list);
这个注解,看起来有点复杂,我们还是直接复制xml版本的sql语句,
复制到这个@Insert("<script></script>")里面就可以
调用
ArrayList<MyStudent> students = Lists.newArrayList(new MyStudent("张三三", 19), new MyStudent("李思思", 19));
int all = myStudentMapper.insertAll(students);
System.out.println("all = " + all);
十二、批量删除
12.1 xml 批量删除
在接口中,增加批量删除的方法
// 批量删除,long... 可变长参数
int deleteAll(long... ids);
解释:
...表示 可变参数,我们进行删除时,(根据id进行删除)sql大概这个格式
delete from MyStudent where id in (20112,202223,20334)
传入的参数是一个可变长度的数组,数组的每个元素是long类型。
修改xml文件
<delete id="deleteAll">
delete from MyStudent where id in
<foreach collection="array" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</delete>
解释:
我们最终要拼成的sql,大概是这个格式
delete from MyStudent where id in (20112,202223,20334)
collection="array" 我们传入的参数就是一个数组,array
open="(" close=")" ,sql中,我们的参数在一个括号() 中。这个是来拼接这个()的
item="id" 数组中,每个元素
separator="," 数组中,每个元素用逗号分割
调用:
int deleteAll = myStudentMapper.deleteAll(201215137, 201215138);
System.out.println("deleteAll = " + deleteAll);
12.2 sql注解删除
在接口中,增加批量删除的方法
int deleteAll(long... ids);
给方法增加sql注解
// 批量删除,long... 可变长参数
@Delete("<script> delete from MyStudent where id in \n" +
" <foreach collection=\"array\" open=\"(\" close=\")\" item=\"id\" separator=\",\">\n" +
" #{id}\n" +
" </foreach> </script>")
int deleteAll(long... ids);
这个注解,看起来有点复杂,我们还是直接复制xml版本的sql语句,
复制到这个@Insert("<script></script>")里面就可以
调用:
int deleteAll = myStudentMapper.deleteAll(201215137, 201215138);
System.out.println("deleteAll = " + deleteAll);