文章目录
mybatis概述
-
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项 目由apache software foundation 迁移到了google code, 并且改名为MyBatis 。2013年11月迁移到Github。
-
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
-
它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程
-
它使用了ORM思想(Object Relationship Mapping)实现了结果集的封装。
mybatis的HelloWorld
入门步骤
- 下载安装mybaits,对于maven工程只需要在pom.xml文件添加mybatis的坐标依赖。Maven中央仓库地址:https://mvnrepository.com/,搜索mybatis的坐标依赖
- 使用Idear创建一个maven工程
- 在pom.xml文件中添加mybatis核心包+mybatis依赖包+数据库驱动包(mysql)
- 创建mybaits的核心配置文件mybatis-config.xml文件
- 登录mybatis官网https://mybatis.org/mybatis-3/zh/index.html,粘贴xml约束
- 登录mybatis官网https://mybatis.org/mybatis-3/zh/index.html,粘贴xml约束
- 修改里面的配置为
- 配置日志文件,创建log4j.properties,将以下的内容赋值进去
- 创建UserMapper.java接口文件和配置UserMapper.xml文件(resources资源文件夹)
粘贴到项目中mapper中.
UserMapper.java接口中的信息。
备注:
UserMapper.xml文件需要和UserMapper.java同名同路径下。
在idea中创建目录的时候,它和包是不一样的
包在创建时:com.zhiyou100.dao它是三级结构
目录在创建时:com.zhiyou100.dao是一级目录 - 定义一个测试类,验证mybatis-config.xml和UserMapper.xml文件信息
- 加载mybatis-config.xml核心配置文件(存放在类路径下 classpath)
- 使用构建者类SqlSessionFactoryBuilder构建SqlSessionFactory工厂对象
- 通过工厂对象创建SqlSession对象
- 使用sqlSession对象创建UserMapper对应的代理对象
- 使用UserMapper代理对象调用对应的接口方法完整对数据库的操作
HelloWorld讲解
- namespace,必须要进行设置,如果不设置,文件无法加载可以表示当前mapper中的增删改查数据哪个命名空间,用以区别 其他的sql中的内容
- #{任意写} 和 KaTeX parse error: Expected 'EOF', got '#' at position 15: {value}**的区别, #̲{任意写} 用来表示sql中的…{value} 用来表示字符串的拼接**
- 核心配置文件中的标签用来在核心配置文件中引入对应的mapper文件
- mapper配置文件是用来书写sql语句的,一个配置文件中只能有一个mapper标签,mapper标签内部有增删改查标签,用来书写增删改查操作
- 增删改查标签中的parameterType属性为设置执行sql语句的时候传过来的值的类型
- 增删改查标签中的resultType属性为设置执行sql语句的时候返回值的类型
- 如果返回值是list,返回值的类型同样还是写成对应集合中存取对象的类型
mybatis进行传统dao层开发
-
需要创建dao接口的实现类
-
开发步骤:
- 在接口实现类中定义SqlSessionFactory属性- 重写接口实现类的构造方法,设置SqlSessionFactory参数 - 通过工厂对象创建SqlSession对象 - 使用sqlSession的增删改查api方法
mapper动态代理开发
- 创建接口写接口方法确保4个一致
- 方法的返回值和对应标签内的resultType一致
- 方法的参数和parameterType一致
- namespace和接口的全名称一致
mybatis的crud操作
<!--mapper配置信息-->
<mapper namespace="com.zhiyou100.dao.UserMapper">
<!--查询用户所有信息-->
<select id="getAllUsers" resultType="com.zhiyou100.pojo.User">
select * from user
</select>
<!--
// 根据id查询用户
User getUserById(int id);
// 查询用户的总数
int getUserTotal();
// 根据用户名称模糊查询
List<User> fuzzyQueryUserByUsername(String username);
// 添加用户信息
void addUser(User user);
// 修改用户信息
void modifyUser(User user);
// 根据id删除用户信息
void deleteUserById(int id);
-->
<!--根据id查询用户-->
<select id="getUserById" parameterType="int" resultType="com.zhiyou100.pojo.User">
select * from user where id = #{id};
</select>
<!--查询用户的总数-->
<select id="getUserTotal" resultType="int">
select count(*) from user
</select>
<!--根据用户名称模糊查询-->
<select id="fuzzyQueryUserByUsername" parameterType="String" resultType="com.zhiyou100.pojo.User">
select * from user where username like '%' #{username} '%'
</select>
<!--添加用户信息-->
<insert id="addUser" parameterType="com.zhiyou100.pojo.User">
insert into user values (null,#{username},#{birthday},#{sex},#{address})
</insert>
<!--修改用户信息-->
<update id="modifyUser" parameterType="com.zhiyou100.pojo.User">
update user set username = #{username},birthday = #{birthday},sex = #{sex},address = #{address} where id = #{id}
</update>
<!--根据id删除用户信息-->
<delete id="deleteUserById" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>
// 测试类UserTest
// 定义全局变量
private InputStream is;
private SqlSession sqlSession;
private UserMapper userMapper;
//初始化mybatis用到的类
@Before
public void init() throws IOException {
// 加载mybatis-config.xml核心配置文件(存放在类路径下 classpath)
is = Resources.getResourceAsStream("mybatis-config.xml");
// 使用构建者类SqlSessionFactoryBuilder构建SqlSessionFactory工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 通过工厂对象创建SqlSession对象
sqlSession = factory.openSession();
// 使用sqlSession对象创建UserMapper对应的代理对象
userMapper = sqlSession.getMapper(UserMapper.class);
}
// 释放mybatis资源
@After
public void release() throws IOException {
sqlSession.commit();
sqlSession.close();
is.close();
}
/**
* 使用mybatis传统方式开发 依赖于dao接口实现类
*/
@Test
public void testGetAllUsers2() throws IOException {
// 加载mybatis-config.xml核心配置文件(存放在类路径下 classpath)
is = Resources.getResourceAsStream("mybatis-config.xml");
// 使用构建者类SqlSessionFactoryBuilder构建SqlSessionFactory工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// 创建UserMapper接口实现类
UserMapper userMapper = new UserMapperImpl(factory);
// 调用userMapper接口中的方法
List<User> users = userMapper.getAllUsers();
for (User user : users) {
System.out.println(user);
}
}
// 根据id查询用户
@Test
public void testGetUserById() {
User user = userMapper.getUserById(41);
System.out.println(user);
}
// 查询用户的总数
@Test
public void testGetUserTotal() {
int total = userMapper.getUserTotal();
System.out.println(total);
}
// 根据用户名称模糊查询
@Test
public void testFuzzyQueryUserByUsername(){
List<User> users = userMapper.fuzzyQueryUserByUsername("王");
System.out.println(users);
}
// 添加用户信息
@Test
public void testAddUser() {
User user = new User(null, "孙行者", new Date(), '男', "花果山");
userMapper.addUser(user);
}
// 修改用户信息 根据id修改
@Test
public void testModifyUser() {
User user = new User(52, "者行孙", new Date(), '男', "花果山");
userMapper.modifyUser(user);
}
// 根据id删除用户信息
@Test
public void testDeleteUserById() {
userMapper.deleteUserById(52);
}
mybatis的多参数
在使用mybatis动态代理模式开发的时候,如果接口中的参数有多个的话如:
// 根据用户名和性别检查用户是否存在
User checkUser( String username,char sex);
- 按参数序号设置
默认序号从0开始
-
在mapper的配置文件中不写 parameterType
-
在使用参数的地方按照 #{0},0代表第一个参数
<!--检查用户是否存在-->
<select id="checkUser" resultType="com.zhiyou100.pojo.User">
select * from user where username = #{0} and sex = #{1};
</select>
- 此方法只用于设置 sql 中的字段的值,只能用 #{序号} 不能使用 ${序号}
注意事项:目前最高只适用于mybatis3.4.1版本
- 通过@Param注解设置参数
通过注解形式给参数指定别名,供mapper文件中的sql语句使用,如果是占位符使用 #{别名},如果是字符串拼接使用 ${别名}
- 在接口中给参数添加注解
User checkUser(@Param(“username”) String username,@Param(“sex”) char sex);
- 在mapper的配置文件中不写parameterType
- 在使用参数的地方按照 #{别名} 或者 ${别名}
<select id="checkUser" resultType="com.zhiyou100.pojo.User">
select * from user where username = #{username} and sex = #{sex}
</select>
// 根据用户名和性别检查用户是否存在
@Test
public void testCheckUser() {
User user = userMapper.checkUser("老王", '女');
System.out.println(user);
}
== 注意:也可以传输sql字段名==
// 根据用户地址查询用户信息
List<User> fuzzyQueryUserByAddress(@Param("address") String address,@Param("content") String content);
<!--根据用户地址模糊查询用户信息-->
<select id="fuzzyQueryUserByAddress" resultType="com.zhiyou100.pojo.User">
select * from user where ${address} like '%' #{content} '%'
</select>
- 调用的时候正常使用
// 根据用户地址查询用户信息
@Test
public void testFuzzyQueryUserByAddress() {
List<User> users = userMapper.fuzzyQueryUserByAddress("address", "郑州");
for (User user : users) {
System.out.println(user);
}
}
- 适用于mybaits各个版本。
mybatisconfig.xml配置文件
- properties属性引入外部的properties文件,可以用于引入外部的数据库连接文件,使用的时候使用el表达式进行引入, 路径是src路径 ,其内部有标签,如果两个都进行设置, 会先加载内部的property再加载外部的properties的resource属性
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
mybatis-config.xml
<!-- 引入db.properties文件 -->
<properties resource="db.properties"></properties>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 使用EL表达式获取对应的值 -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
- typeAliases类型–>别名属性,在mapper文件中,如果使用参数类型或者返回值类型的时候需要指定类的全名,可以使用别名来进行配置使用其内部的标签<typeAliases><typeAlias type=“com.zhiyou100.pojo.User” alias=“user”></typeAlias></typeAliases>,将对应的类的别名设置为User或者使用<package name=“com.zhiyou100.pojo”/>,会自动扫描当前包和其子包将别名配置为类名首字母大写 (User) 和 类名小写(user), 推荐使用这种
<typeAliases>
<!--
设置com.zhiyou100.pojo.User的别名为User,如果这样设置,每一个pojo都需要设置
-->
<!-- <typeAlias type="com.zhiyou100.pojo.User" alias="User"/> -->
<!--
会自动设置当前包和其子包中的所有的类的别名为User或者user
一般在开发的过程中使用package
-->
<package name="com.zhiyou100.pojo"/>
</typeAliases>
- mybatis内部配置的别名,在mapper中写哪个都可以
如:
<!-- 此处parameterType 里面既可以填写int 也可以添加INT 也可以添加java.lang.Integer 还可以填写Integer-->
<delete id="deleteUserById" parameterType="int">
delete from user where id = #{id}
</delete>
- mappers映射器属性,内部设置的标签<mapper>是用来设置
- <mapper resource=“com/zhiyou100/dao/UserMapper.xml”/> 中的resource指定的是classpath路径不是相对路径 。
- <mapper class=“com.zhiyou100.dao.UserMapper”/>通过接口文件找到对应的xml文件,此种状态下必须保证 xml文件和接口名称相同,且放在同一个包下 。
- <package name=“com.zhiyou100.dao”/>会扫描指定包下及其子包中的所有的mapper文件,此种状态下必须保证xml文件和接口名称相同,且放在同一个包下
mybatis注解开发
-
对于像 UserMapper 这样的映射器类来说,还有另一种方法来完成语句映射。 它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置;
-
用注解来映射简单语句会使代码显得更加简洁。
实例:
// 查询所有用户
@Select("select * from user")
List<User> getAllUsers();
- 调用的时候,正常调用。
@Test
public void getAllUsers() {
List<User> user = userMapper.getAllUsers();
System.out.println(users);
}
- 注意事项:如果对接口同一个方法既做了xml配置映射,又做了注解扫描,那么程序执行时会爆出 :Mapped Statements collection already contains value for com.zhiyou100.dao.UserMapper.getAllUsers
注解开发的增删改查crud
示例如下:
@Select("select * from user from user where username like '%'
#{username} '%'")
// 根据用户名称模糊查询
List<User> fuzzyQueryUserByUsername(String username);
// 添加用户信息
@Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")
void addUser(User user);
// 修改用户信息
@Update("update user set username = #{username},birthday = #{birthday},sex = #{sex},#{address} where id = #{id}")
void modifyUser(User user);
// 根据id删除用户信息
@Delete("delete from user where id = #{id}")
void deleteUserById(int id);
补充一:#{}和${}的区别
- #{} 表示一个占位符 ?
- 通过#{} 可以实现preparedStatement向占位符中设置值 ,自动进行类型的转换[Java类型和jdbc类型的转换]
- #{} 可以有效防止sql的非法注入
- #{} 可以接收简单类型或者pojo属性值
- 如果parameteType传输单个简单类型值,#{}括号中可以是value,或者其他名称
- ${} 表示字符串的拼接 大多数使用在 输出sql字段名
- 使用${}可以将parameteType传入的内容拼接在sql中 ,不进行类型的转换
- ${} 可以接收简单类型值或者pojo属性值
- 如果parameteType传输单个简单类型值,${}括号中的只能value
补充二:mybatis中:mapper.xml中使用比较运算符需要进行转义【 > < 】 = !=
在sql语句中日期可以直接进行大小比较,使用比较运算符 >= <= > < = !=
> ----> 大于号
< ----> 小于号
或者使用 <![CDATA[ ]]> 把需要比较的条件放进[]里面即可。
如日期比较:
select * from user where birthday > "2021-2-28"
select * from user where <![CDATA[ birthday < "2021-2-28" ]]>
补充三:新增用户ID的返回值
新增用户后,同时还要返回当前新增用户id值,一般主键id值是自增的,所以我们可以把新自增的id值返回。
SELECT LAST_INSERT_ID();
<!--keyColumn:数据库字段(key值) keyProperty(实体类对应的数据库key值) order:(AFTER[在sql执行之前],BEFORE[在sql执行之后]) resultType(返回值类型)-->
<selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
备注:
mybaits注解开发对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的SQL语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。