MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc复杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由Mybatis框架执行sql并将结果映射成java对象并返回。
MyBatis架构
配置MyBatis
在classpath下创建SqlMapConfig.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> <!-- 和spring整合后 environments配置将废除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123" /> </dataSource> </environment> </environments> </configuration>
在classpath下的sqlmap目录下创建sql映射文件users.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="test"> </mapper>
namespace:命名空间,用于隔离sql语句。
1.必须是接口的全限定名
2.Statementid必须和接口的方法名称一致
3.接口方法的参数类型要和parameterType要一致
4.接口方法的返回值类型要和resultType一致
映射文件:
<!-- 根据id获取用户信息 --> <select id="findUserById" parameterType="int" resultType="com.baidu.mybatis.po.User"> select * from user where id = #{id} </select>
#{}作用就是占位符,相当于jdbc的“?”;
parameterType:查询的参数类型。
resultType:查询结果的数据类型,如果是pojo应该给全路径
mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml
<mappers> <mapper resource="sqlmap/User.xml"/> </mappers>
private SqlSessionFactory sqlSessionFactory=null; @Before public void init() throws Exception{ //第一步:创建一个SQLSessionFactoryBuilder对象。 SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder(); //第二部:加载配置文件 InputStream inputStream=Resources.getResourceAsStream("SqlMapConfig.xml"); //第三步:创建SQLSessionFactory对象 sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); } @Test public void getUserById() throws Exception { // 第四步:创建SQLSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 第五步:使用SQLSession对象执行查询,得到User // 第一个参数:执行查询statementId User user = sqlSession.selectOne("getUserById", 10); // 第六步:打印结果 System.out.println(user); // 第七步:释放资源 sqlSession.close(); }
根据用户名查询用户信息
在user.xml中添加
<!-- 如果查询结果返回list。resultType设置为list中一个元素对的数据类型 ${}字符串拼接指令 --> <select id="getUserByName" parameterType="string" resultType="java.lang.String"> SELECT * FROM USER WHERE username LIKE '%${value}%'; </select>
parameterType:定义输入到sql中的映射类型,
{value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
resultType:定义结果映射类型。
代码测试
@Test public void getUserByName()throws Exception{ //创建一个SQLSession对象 SqlSession session = sqlSessionFactory.openSession(); //执行查询 List<User>list=session.selectList("getUserByName","%张%"); for (User user : list) { System.out.println(user); } //释放资源 session.close(); }
#{}和$ {}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符设置,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个类型值,#{}括号中可以是value或其它名称。
$ {}表示拼接sql串,通过$ {}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,$ {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,$ {}括号中只能是value
parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象
selectOne和selectList
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常
selectList可以查询一条或多条记录。
添加用户
在SqlMapConfig.xml中添加
<insert id="insertUser" parameterType="com.baidu.mybatis.po.User"> <!-- selectKey将主键返回,需要再返回 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}); </insert>
添加selectKey实现将主键返回
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
@Test public void addUser()throws Exception{ //创建一个SQLSession对象 SqlSession session = sqlSessionFactory.openSession(); //创建User对象 User user=new User(); user.setUsername("赵四"); user.setSex("男"); user.setBirthday(new Date()); user.setAddress("北京"); session.insert("insertUser",user); //提交 session.commit(); session.close(); }
删除用户
映射文件
<!-- 删除用户 --> <delete id="deleteUserById" parameterType="int"> delete from user where id=#{id} </delete>
@Test public void deleteUser()throws Exception{ SqlSession session = sqlSessionFactory.openSession(); session.delete("deleteUser",27); session.commit(); session.close(); }
修改用户
<!-- 修改用户 --> <update id="updateUser" parameterType="com.baidu.mybatis.po.User"> update user set username=#{username} where id=#{id} </update>
@Test public void updateUser()throws Exception{ SqlSession sqlSession = sqlSessionFactory.openSession(); User user=new User(); user.setUsername("王六"); user.setId(26); sqlSession.update("updateUser",user); sqlSession.commit(); sqlSession.close(); }
一.SqlSession的使用范围
SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
(1).SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory产生,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
(2).SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory.
(3).6.2.3 SqlSession
SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
SqlMapConfig.xml配置文件
1.配置内容
SqlMapConfig.xml中配置的内容和顺序:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
evironments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
2.properties(属性)
SqlMapConfig.xml可以引用java属性文件中的配置信息
在classpath下定义db.properties文件,
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 jdbc.username=root jdbc.password=root
SqlMapConfig.xml
<properties resource="db.properties"/> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <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>
注意: MyBatis 将按照下面的顺序来加载属性:
(1): 在 properties 元素体内定义的属性首先被读取。
(2): 然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。
3.自定义别名
简单用法
4.7.4.3 < package name=""/> < mappers> 基于classPath查询 根据接口名称加载mapper文件 要求:1.mapper映射文件和接口在同一个目录下 2.mapper映射文件的名称和接口名称一致 3.class就是接口的权限定名 < /mappers>