Mybatis详解

    xiaoxiao2022-06-24  28

    Mybatis详解

    关于Mybatis的具体介绍请参考http://www.mybatis.org/mybatis-3/zh/

    使用Mybatis时,直接导入相应的jar包就行,这里使用的是mybatis-3.4.1.jar

    下面的例子,已一个users表为例,先创建表,再插入两条数据

    CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT); INSERT INTO users(NAME, age) VALUES('Tom', 12); INSERT INTO users(NAME, age) VALUES('Jack', 11);

    创建Mybatis程序的大致步骤是:

    1.添加Mybatis 的配置文件Configuration.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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="" value="" /> </transactionManager> <dataSource type="UNPOOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="" /> </dataSource> </environment> </environments> </configuration>

    一些说明:

    a.transactionManager-事务管理器,在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):

    JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)

    b.dataSource-数据源,dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源

    2.创建实体类User和定义操作users 表的sql 映射文件userMapper.xml

    首先创建实体类User

    public class User { private int id; private String name; private int age; public int getId() { return id; } //get set方法 ...... }

    然后创建user表的sql映射文件userMapper.xml 在这里定义了一个select语句,根据id查询到一个user对象

    <?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="mybatis.test1.userMapper"> <!--根据id查询到一个user对象 --> <select id="getUser" parameterType="int" resultType="mybatis.test1.User"> select * from users where id=#{id} </select> </mapper>

    注意的点:

    #{id}-表示从传递过来的参数中取出id值namespace-相当于是唯一标识符,一般是包名+文件名parameterType-表示参数的类型,这里是intresultType表示的是返回值类型,这里是User类的全类名

    3.在Configuration.xml文件中注册userMapper.xml 文件

    注意:这里是路径的结构,不是包的结构

    <mappers> <mapper resource="mybatis/test1/userMapper.xml" /> </mappers>

    4.执行定义的select 语句

    String resource = "Configuration.xml"; //加载mybatis 的配置文件(它也加载关联的映射文件) Reader reader = Resources.getResourceAsReader(resource); //构建sqlSession 的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //创建能执行映射文件中sql 的sqlSession SqlSession session = sessionFactory.openSession(); //映射sql 的标识字符串 String statement = "mybatis.test1.userMapper"+".getUser"; //执行查询返回一个唯一user 对象的sql User user = session.selectOne(statement, 1); System.out.println(user);

    这里的statement是userMapper.xml中mapper的namespace属性,加上select的id属性

    String statement = "mybatis.test1.userMapper"+".getUser";

    最后控制台输出的数据结果为:

    User [id=1, name=Tom, age=12]

    5.输出调用sql语句 为方便调试,可在控制条输出调用sql语句,具体实现参考MyBatis控制台输出SQL语句,注意settings标签的顺序

    增删改查操作

    有两种方式实现增删改查操作:

    XML实现注解实现

    XML实现

    添加数据

    添加数据要使用insert标签,如下:

    <insert id="addUser" parameterType="mybatis.test2.User"> insert into users(name, age) values(#{name}, #{age}) </insert> parameterType表示参数的类型使用的是实体类User对象的全类名。values(#{name}, #{age}中#{}括号中对应的是实体类User类的属性

    编写测试类,测试下:

    @Test public void testAdd() { int insert = session.insert("mybatis.test2.userMapper.addUser", new User(-1, "xiaozhao", 23)); System.out.println(insert); }

    返回值insert表示受影响的行数,此时提示是1,表示是成功的,但是此时去查看数据库,会发现并没有插入的数据。是因为session = sessionFactory.openSession();是需要手动提交事务的,所以需要使用如下的方式:

    int insert = session.insert("mybatis.test2.userMapper.addUser", new User(-1, "xiaozhao", 23)); session.commit();

    设置自动提交

    session = sessionFactory.openSession(true);

    删除数据

    删除数据使用delete标签

    <delete id="deleteUser" parameterType="int"> delete from users where id=#{id} </delete>

    测试如下:

    int delete = session.delete("mybatis.test2.userMapper.deleteUser", 6); session.commit();

    修改数据

    修改数据使用update标签

    <update id="updateUser" parameterType="mybatis.test2.User"> update users set name=#{name}, age=#{age} where id=#{id} </update>

    测试如下:

    int insert = session.update("mybatis.test2.userMapper.updateUser", new User(4, "xiaowang", 30)); session.commit();

    查询数据

    查询单个对象

    在xml中的配置如下:

    <!--根据id查询到一个uesr对象 --> <select id="getUser" parameterType="int" resultType="mybatis.test2.User"> select * from users where id=#{id} </select>

    使用selectOne方法获取查询的对象:

    User user = session.selectOne("mybatis.test2.userMapper.getUser", 1); session.commit(); System.out.println(user);

    查询所有对象

    查询所有对象,表示返回值有多个对象,resultType表示list里面放的对象类型 在xml中配置如下:

    <select id="getAllUsers" resultType="mybatis.test2.User"> select * from users </select>

    使用selectList获取所有对象,测试如下:

    List<User> users = session.selectList("mybatis.test2.userMapper.getAllUsers"); session.commit(); System.out.println(users);

    注解实现

    基于注解实现,需先定义sql映射的接口,把所有的sql语句写到接口中

    package mybatis.test3; 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 mybatis.test2.User; public interface UserMapper { @Insert("insert into users(name, age) values(#{name}, #{age})") public int add(User user); @Delete("delete from users where id=#{id}") public int deleteById(int id); @Update("update users set name=#{name}, age=#{age} where id=#{id}") public int update(User user); @Select("select * from users where id=#{id}") public User getById(int id); @Select("select * from users") public List<User> getAll(); }

    将接口文件添加到Configuration.xml的mappers中,注意与映射文件的区别

    <mappers> <mapper class="mybatis.test3.UserMapper" /> </mappers>

    测试添加如下:

    UserMapper mapper = session.getMapper(UserMapper.class); int add = mapper.add(new User(-1, "xiaoqian", 23)); session.commit(); System.out.println(add);

    优化

    数据库连接单独放在一个文件

    创建db.properties文件

    driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis username=root password=

    在Configuration.xml中导入文件

    <properties resource="db.properties"></properties>

    在dataSource标签中引用这些值:

    <dataSource type="UNPOOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource>

    为实体类定义别名,简化sql 映射xml 文件中的引用

    1.定义别名 在上述的的映射文件中,总在重复的写全类名,如mybatis.test1.User,而mybatis.test1.User在很多地方都要重用

    <select id="getUser" parameterType="int" resultType="mybatis.test1.User"> select * from users where id=#{id} </select>

    所以可以在Configuration.xml中配置全类名的别名

    <!-- 配置实体类的别名 --> <typeAliases> <typeAlias type="mybatis.test2.User" alias="_User"/> </typeAliases>

    使用别名

    <select id="getAllUsers" resultType="_User"> select * from users </select>

    2.扫描包方式

    参考Mybatis之typeAlias配置的3种方法

    通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean, 并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。

    <typeAliases> <package name="cn.lxc.vo" /> </typeAliases>

    3.注解方式

    package cn.lxc.vo; import org.apache.ibatis.type.Alias; @Alias("User") public class User { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

    可以在src 下加入log4j 的配置文件,打印日志信息

    添加相应的jar包, log4j.properties配置信息如下:

    log4j.properties, log4j.rootLogger=DEBUG, Console #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.logger.java.sql.ResultSet=INFO log4j.logger.org.apache=INFO log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG

    也可以使用xml方式来配置log4j,如下的log4j.xml

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="debug" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>

    解决字段名与实体类属性名不相同的冲突

    如下的例子中,表中的列名为order_no,而实体类中的属性名为orderNo,如何把它们对应起来呢?

    创建如下的orders表:

    CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23); INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33); INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);

    创建orders表对应的实体类,Order:

    package mybatis.bean; public class Order { private int id; private String orderNo; private float price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public Order() { } public Order(int id, String orderNo, float price) { super(); this.id = id; this.orderNo = orderNo; this.price = price; } @Override public String toString() { return "Order [id=" + id + ", orderNo=" + orderNo + ", price=" + price + "]"; } }

    可以发现,字段名和属性名并不一致。

    创建orderMapper.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="mybatis.test4.orderMapper"> <!--根据id查询到一个order对象 --> <select id="getOrder" parameterType="int" resultType="mybatis.bean.Order"> select * from orders where order_id=#{id} </select> </mapper>

    使用如下方式来获取order对象:

    Order order = session.selectOne("mybatis.test4.orderMapper.getOrder", 1); System.out.println(order);

    会发现输出结果为null

    如何显示order的查询呢? 1.通过在sql 语句中定义别名

    如下给order_id起别名为id等等,是表的字段名与实体类属性名对应

    <select id="getOrder" parameterType="int" resultType="mybatis.bean.Order"> select order_id id, order_no orderNo, order_price price from orders where order_id=#{id} </select>

    这样之后,就可以正常获取值了

    Order [id=1, orderNo=aaaa, price=23.0]

    2.使用<resultMap>

    使用<resultMap>来把表的字段名与实体类属性名对应

    注意此时<select>标签中就要使用resultMap(不是resultType)来对应<resultMap>标签中id的值

    <!-- resultMap封装映射关系 --> <resultMap type="mybatis.bean.Order" id="orderMap"> <!-- 针对主键 --> <id property="id" column="order_id"/> <result property="orderNo" column="order_no"/> <result property="price" column="order_price"/> </resultMap> <select id="getOrder" parameterType="int" resultMap="orderMap"> select * from orders where order_id=#{id} </select>

    接口编程方式实现

    上面使用的方式是用户比较熟悉的方式。现在有个更好的方式是,使用接口来描述statement的参数和返回值,这样执行起来可以更简洁和安全

    如下的例子,先创建一个tbl_employee表,插入一条数据

    create table tbl_employee( id int(11) primary key auto_increment, last_name varchar(255), gender char(1), email varchar(255) ); insert into tbl_employee (last_name, gender, email) values('wz', 0, 'wz@123.com')

    创建对应的实体类Employee类

    public class Employee { private Integer id; private String lastName; private String email; private String gender; //get set方法 ...... }

    如下先创建一个接口类EmployeeMapper

    package com.wz.mybatis.dao; import com.wz.mybatis.bean.Employee; public interface EmployeeMapper { //更加id获取Employee public Employee getEmpById(Integer id); }

    接口要与映射文件EmpolyeeMapper.xml动态绑定,而对于xml映射文件EmpolyeeMapper.xml要注意:

    namespace要指定为接口的全类名select标签的id要与接口的方法名对应

    EmpolyeeMapper.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.wz.mybatis.dao.EmployeeMapper"> <select id="getEmpById" resultType="com.wz.mybatis.bean.Employee"> select id, last_name lastName, gender, email from tbl_employee where id = #{id} </select> </mapper>

    其调用方式如下:

    public SqlSessionFactory getSqlSessionFactory() throws IOException{ String resource = "mybatis-config.xml"; // 加载mybatis 的配置文件(它也加载关联的映射文件) Reader reader = Resources.getResourceAsReader(resource); // 构建sqlSession 的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); return sessionFactory; } public void test01() throws IOException { // 构建sqlSession 的工厂 SqlSessionFactory sessionFactory = getSqlSessionFactory(); // 创建能执行映射文件中sql 的sqlSession SqlSession session = sessionFactory.openSession(); try { //获取接口的实现类对象 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); } finally { session.close(); } }

    其中System.out.println(mapper.getClass());的控制台输出的结果为class com.sun.proxy.$Proxy4,表示的是Mybatis会为接口创建一个代理对象,代理对象去执行增删改查方法

    转载请注明原文地址: https://ju.6miu.com/read-1123860.html

    最新回复(0)