MyBatis-XML和注解
参考:
https://www.cnblogs.com/lyc-smile/p/9055856.html
https://ld246.com/article/1488810828678
https://blog.csdn.net/qq_41617744/article/details/80224721
Mybatis之XML、注解的使用
前言
上篇简单介绍了Mybatis的简单实用,本篇先对上次实验环境的一些内容进行优化,然后验证Mybatis的XML配置以及注解方式。
实验环境优化
数据库配置
在mybatis的配置文件中,引入数据库配置文件db.properties,然后修改配置文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis name=root password=admin
mybatis配置文件 mybatis-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"/> <!-- development : 开发模式 work : 工作模式 --> <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="${name}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/lion/mapper/UserMapper.xml" /> </mappers> </configuration>
实体类定义别名
没有为实体定义别名时,在sql映射xml中应用实体时,比如parameterType resultType 中就需要配置实体的全路径名(全限定名)。
当为实体定义了别名后,映射文件中可以直接配置实体的别名即可。因此为实体类定义别名,可以简化Sql映射xml文件中对实体的引用配置。
mybatis配置文件中<typeAlises>定义实体别名有两种方式:
- typeAlias 单个为每个实体定义别名 当实体类比较多是 配置增多 不方便
- package 指定实体的包 会自动为改包下的所有实体自动设定各自的类名为别名
优化后的Mybatis配置文件mybatis-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> <!-- 此种方式是分别为每一个实体设置别名 mapper xml 中resultType即为alias的值--> <!-- <typeAlias type="com.lion.pojo.User" alias="_User"/> --> <!-- package 设置别名的方式会自动为该包下的所有JavaBean设置别名为其类名称 --> <package name="com.lion.pojo"/> </typeAliases> <!-- development : 开发模式 work : 工作模式 --> <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="${name}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/lion/mapper/UserMapper.xml" /> </mappers> </configuration>
Mybatis实现方式
分别使用XML和注解的方式实现对User的CURD。
XML方式
sql中参数定义为 #{} 在Mybatis配置文件中已经配置对实体类的自动设置别名,因此此处可以直接使用实体类的别名进行引用。
<?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.lion.mapper.UserMapper"> <select id="selectUser" parameterType="int" resultType="User"> select * from users where id = #{id} </select> <delete id="deleteUser" parameterType="int"> delete from users where id = #{id} </delete> <update id="updateUser" parameterType="User"> update users set name = #{name},age = #{age} where id = #{id} </update> <insert id="addUser" parameterType="User"> insert into users(name,age) values(#{name},#{age}) </insert> <select id="selectAll" resultType="User" > select * from users </select> </mapper>
1 package com.lion.test; 2 3 import java.io.IOException; 4 import java.util.List; 5 6 import org.apache.ibatis.session.SqlSession; 7 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.junit.Test; 9 10 import com.lion.pojo.User; 11 import com.lion.util.MybatisUtils; 12 13 public class TestUserCURDByXML { 14 15 @Test 16 public void testAdd() { 17 try { 18 SqlSessionFactory factory = MybatisUtils.getFactory(); 19 SqlSession session = factory.openSession(); 20 21 String statement = "com.lion.mapper.UserMapper.addUser"; 22 // id mysql设置的自增长 此处设为 -1 23 User user = new User(-1, "Spring", 25); 24 session.insert(statement, user); 25 26 // 不提交的话 数据无法提交到数据库 27 session.commit(); 28 session.close(); 29 } catch (IOException e) { 30 e.printStackTrace(); 31 } 32 } 33 34 @Test 35 public void testDelete() { 36 try { 37 SqlSessionFactory factory = MybatisUtils.getFactory(); 38 // 自动提交事务 39 SqlSession session = factory.openSession(true); 40 41 String statement = "com.lion.mapper.UserMapper.deleteUser"; 42 session.delete(statement, 4); 43 44 session.close(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 } 49 50 @Test 51 public void testUpdate() { 52 try { 53 SqlSessionFactory factory = MybatisUtils.getFactory(); 54 // 自动提交事务 55 SqlSession session = factory.openSession(true); 56 57 String statement = "com.lion.mapper.UserMapper.updateUser"; 58 User user = new User(1, "mali", 18); 59 session.update(statement, user); 60 61 session.close(); 62 } catch (IOException e) { 63 e.printStackTrace(); 64 } 65 } 66 67 @Test 68 public void testSelect() { 69 try { 70 SqlSessionFactory factory = MybatisUtils.getFactory(); 71 // 自动提交事务 72 SqlSession session = factory.openSession(true); 73 74 String statement = "com.lion.mapper.UserMapper.selectAll"; 75 List<User> users = session.selectList(statement); 76 for (User user : users) { 77 System.out.println(user); 78 } 79 80 session.close(); 81 } catch (IOException e) { 82 e.printStackTrace(); 83 } 84 } 85 86 }
注解方式
package com.lion.testAnnotation; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import com.lion.pojo.User; public interface UserMapper { @Insert("insert into users(name,age) values(#{name},#{age})") int insertUser(User user); @Delete("delete from users where id = #{id}") int deleteUser(int id); @Update("update users set name = #{name},age = #{age} where id = #{id}") int updateUser(User user); @Select("select * from users where id = #{id}") User selectUser(int id); @Select("select * from users") List<User> selectAll(); }
Mybatis配置文件中注册映射接口 class
<mappers> <mapper resource="com/lion/mapper/UserMapper.xml" /> <mapper class="com.lion.testAnnotation.UserMapper"/> </mappers>
针对同一实体的映射文件不能放到同一个包中。
1 package com.lion.testAnnotation; 2 3 import java.io.IOException; 4 import java.util.List; 5 6 import org.apache.ibatis.session.SqlSession; 7 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.junit.Before; 9 import org.junit.Test; 10 11 import com.lion.pojo.User; 12 import com.lion.util.MybatisUtils; 13 14 public class TestUserCURDByAnnotaion2 { 15 16 private SqlSessionFactory factory; 17 18 @Before 19 public void loadFactory() { 20 try { 21 factory = MybatisUtils.getFactory(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 27 @Test 28 public void testAdd() { 29 SqlSession session = factory.openSession(true); 30 // 映射器 31 UserMapper mapper = session.getMapper(UserMapper.class); 32 33 int i = mapper.insertUser(new User(-1, "xiazis", 24)); 34 35 System.out.println(i); 36 37 session.close(); 38 39 } 40 41 @Test 42 public void testDelete() { 43 SqlSession session = factory.openSession(true); 44 // 映射器 45 UserMapper mapper = session.getMapper(UserMapper.class); 46 47 int i = mapper.deleteUser(1); 48 49 System.out.println(i); 50 51 session.close(); 52 53 } 54 55 @Test 56 public void testUpdate() { 57 SqlSession session = factory.openSession(true); 58 // 映射器 59 UserMapper mapper = session.getMapper(UserMapper.class); 60 61 int i = mapper.updateUser(new User()); 62 63 System.out.println(i); 64 65 session.close(); 66 67 } 68 69 @Test 70 public void testSelect() { 71 SqlSession session = factory.openSession(true); 72 // 映射器 73 UserMapper mapper = session.getMapper(UserMapper.class); 74 75 User user = mapper.selectUser(2); 76 77 System.out.println(user); 78 79 session.close(); 80 81 } 82 83 @Test 84 public void testSelectAll() { 85 SqlSession session = factory.openSession(true); 86 // 映射器 87 UserMapper mapper = session.getMapper(UserMapper.class); 88 89 List<User> users = mapper.selectAll(); 90 91 for (User user : users) { 92 System.out.println(user); 93 } 94 95 session.close(); 96 97 } 98 99 }
MyBatis 用注解好还是用 XML 好?
MyBatis 支持注解 SQL 语句,如:
package com.iandtop.jxy.mapper;
import com.iandtop.saas.smartpark.vo.UserVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author andyzhao
*/
@Mapper
public interface LoginMapper {
@Select("select count(*) from sm_user")
Integer retrieveAllCount() throws RuntimeException;
@Select("select * from sm_user WHERE user_password = #{password} and user_code = #{code}")
List<UserVO> retrieveByCodeAndPwd(@Param("code") String code, @Param("password") String password) throws RuntimeException;
@Select("select * from sm_user WHERE user_code = #{code}")
List<UserVO> retrieveByCode(@Param("code") String code) throws RuntimeException;
@Select("SELECT * FROM SM_USER WHERE pk_user = #{pk_user}")
UserVO findByPK(@Param("pk_user") String pk_user);
}
但是常用的还是 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="com.iandtop.jxy.mapper.LoginMapper"> <select id="retrieveAllCount" resultType="java.lang.Integer"> select count(*) from sm_user </select> <select id="retrieveByCodeAndPwd" resultType="com.iandtop.saas.smartpark.vo.UserVO"> select * from sm_user WHERE user_password = #{password} and user_code = #{code} </select> <select id="retrieveByCode" resultType="com.iandtop.saas.smartpark.vo.UserVO"> select * from sm_user WHERE user_code = #{code} </select> </mapper> 作者:haihai 链接:https://ld246.com/article/1488810828678 来源:链滴 协议:CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/
到底选哪一种呢?我选 XML:
- 首先官方也是推荐使用 XML
- 注解方式拼接动态 SQL 功能有限
- Java 又和 SQL 搞到一起了感觉很不爽
网上有说“按需使用",大致意思就是说如果”复杂“就用 XML,剩下的就用注解。那为什么这么复杂,干嘛不干脆用 XML 就得了?
网上有说“注解和 xml 的一起使用”,大致就是一个工程一会用注解一会用 XML。那为什么这么复杂,干嘛不干脆用 XML 就得了?
总结:
- 注解也许有很多优点,但是哪位同胞可以好心告诉我下?
- Java 各个框架太多,能简洁干嘛要复杂?我就奇了怪了。如果整天只是满脑子的各种框架的使用和配置方法那真是弱爆了。
- mybatis强大之处在于他的动态sql,xml的可维护性高。而且在实际开发中表结构往往很复杂,所以在实际开发中建议大家用xml,即便很简单的业务,这样方便统一,也方便日后的维护修改
MyBatis的注解和运行原理
Mybatis的注解:
注解和xml配置文件可以混合使用
MyBatis 的运行原理
在MyBatis运行开始时需要先通过Resources加载全局配置文件.
下面需要实例化SqlSessionFactoryBuilder构建器.帮助SqlSessionFactory接口实现类DefaultSqlSessionFactory.
在实例化DefaultSqlSessionFactory之前需要先创建XmlConfigBuilder解析全局配置文件流,并把解析结果存放在Configuration中.
之后把Configuratin传递给DefaultSqlSessionFactory.到此SqlSessionFactory工厂创建成功.
由SqlSessionFactory工厂创建SqlSession.
每次创建SqlSession时,都需要由TransactionFactory创建Transaction对象,同时还需要创建SqlSession的执行器Executor,
最后实例化DefaultSqlSession,传递给SqlSession接口.
根据项目需求使用SqlSession接口中的API完成具体的事务操作.
如果事务执行失败,需要进行rollback回滚事务.
如果事务执行成功提交给数据库.关闭SqlSession
简化:
第一步:
获取XML文件流对象(Resources)
第二步:
创建一个带有Configuration对象的DefaultSqlSessionFactory对象
此对象用来实例化SqlSession的对象。
第三步:
由DefaultSqlSessionFactory创建SqlSession带有Configuration对象,执行器对象(Executor(Transaction)
小知识: mybatis.xml中直接使用package,进行包的全扫描。用的最多。 resource="StudentMapper.xml" , class="StudentMapper"
|