mybatis开发步骤

MVC模型

Model模型:JavaBean实现,用于封装业务数据UserBean和业务逻辑UserDaoImpl

View视图:JSP+JSTL实现,用于收集客户动作<form>和显示业务数据<table>

Controller控制器:Servlet实现,用于流程控制

MyBatis开发步骤

1、添加依赖

 <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.23</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

2、定义核心配置文件 resources/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="database.properties"/>
    <environments default="dev">
        <environment id="dev">
            <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>
</configuration>

3、创建表

create table t_users(
	id bigint primary key auto_increment,
	username varchar(20) not null unique,
	password varchar(20) not null
)engine=innodb default charset utf8;

根据表结构定义对应的实体类

@Data
public class UserBean implements Serializable {
    private Long id;
    private String username;
    private String password;
}

定义对应的映射元文件 resources/com/yan/mapper/UserBean-mapper.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>
    <resultMap id="baseResultMapper" type="com.yan.entity.UserBean" autoMapping="true">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="username" property="username" jdbcType="VARCHAR"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
    </resultMap>
    <insert id="save" parameterType="com.yan.entity.UserBean" useGeneratedKeys="true" keyProperty="id">
        insert into t_users(username,password) values(#{username},#{password})
    </insert>
</mapper>

jdbcType的设置名称对应的是java.jdbc.Types类中的常量名称

定义映射文件后需要在核心配置文件中进行注册 mybatis-config.xml

    <mappers>
        <mapper resource="com/yan/mapper/UserBean-mapper.xml"/>
    </mappers>

目前一般建议使用Mapper接口的方式进行调用,所以需要添加对应的Mapper接口

public interface UserMapper {
    //对应映射元文件中的insert\update\delete\select标签
    int save(UserBean user);
}

修改映射元文件的名空间和Mapper接口的全名一致

<mapper namespace="com.yan.mapper.UserMapper">

4、定义工具类

重点:4大核心组件的生命周期

public class MybatisSessionFactory {
    private MybatisSessionFactory(){}
    private static SqlSessionFactory factory=null;
    private static final ThreadLocal<SqlSession> sessions=new ThreadLocal<>();

SqlSession是java.sql.Connection对象的浅封装,必须保证及时关闭

public class OpenSessionInViewFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        try{
            chain.doFilter(request, response);
            MybatisSessionFactory.commitTransaction();
        } catch (Exception e){
            MybatisSessionFactory.rollbackTransaction();
            throw new ServletException(e);
        }finally {
            MybatisSessionFactory.closeSession();
        }
    }
}

Filter的配置信息 web.xml

    <filter>
        <filter-name>OpenSessionInView</filter-name>
        <filter-class>com.yan.filters.OpenSessionInViewFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>OpenSessionInView</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>

多表关联的问题

对一查询

学生和班级【产品和类目】

create table t_catalog(
	id bigint primary key auto_increment,
    title varchar(32) not null
)engine=innodb default charset utf8;

create table t_produce(
	id bigint primary key auto_increment,
    name varchar(32) not null,
    catalog_id bigint,
    foreign key(catalog_id) references t_catalog(id) on delete cascade
)engine=innodb default charset utf8;

定义实体类

按照业务分析,可以发现获取类目信息时不需要加载对应类型的产品信息,所以这是一个单向关联关系

public class CatalogBean implements Serializable{
    private Long id;
    private String title;
}

多方的类定义,需要获取一方的信息

public class ProduceBean implements Serializable{
    private Long id;
    private String name;
    private CatalogBean catalog=new CatalogBean();
}

定义映射元文件

如何实现获取产品信息时同时获取对应的类目信息?

写法1:使用级联属性定义

<?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.yan.mapper.ProduceMapper">
    <resultMap id="baseResultMap" type="com.yan.entity.ProduceBean">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <result column="catalog_id" property="catalog.id" jdbcType="BIGINT"/>
        <result column="title" property="catalog.title" jdbcType="VARCHAR"/>
    </resultMap>
    <select id="loadById" parameterType="long" resultMap="baseResultMap">
        select p.*,c.title from t_produce p left join t_catalog c on p.catalog_id=c.id where p.id=#{id}
    </select>
</mapper>

写法2:推荐使用

<resultMap id="baseResultMap" type="com.yan.entity.ProduceBean">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
       <association property="catalog" javaType="com.yan.entity.CatalogBean">
           <id column="catalog_id" property="id" jdbcType="BIGINT"/>
           <result column="title" property="title" jdbcType="VARCHAR"/>
       </association>
    </resultMap>
    <select id="loadById" parameterType="long" resultMap="baseResultMap">
        select p.*,c.title from t_produce p left join t_catalog c on p.catalog_id=c.id where p.id=#{id}
    </select>

写法3:不推荐使用

    <resultMap id="baseResultMap" type="com.yan.entity.ProduceBean">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
       <association property="catalog" select="com.yan.mapper.CatalogMapper.loadById" column="catalog_id"/>
    </resultMap>
    <select id="loadById" parameterType="long" resultMap="baseResultMap">
        select * from t_produce where id=#{id}
    </select>

###association对一

  • select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果。

  • column:将主查询中列的结果作为嵌套查询的参数,配置方式如column="{prop1=col1,prop2=col2}",prop1和prop2将作为嵌套查询的参数。

  • fetchType:数据加载方式,可选值为lazy和eager分别为延迟加载和积极加载。

  • 如果要使用延迟加载,除了将fetchType设置为lazy,还需要注意全局配置aggressiveLazyLoading的值应该为false。这个参数在3.4.5版本之前默认值为ture,从3.4.5版本开始默认值改为false

对多查询

获取订单信息时需要获取对应的订单详情信息

create table t_order(
	id bigint primary key auto_increment
    order_date timestamp default current_timestamp,
    all_price numeric(8,2)
)engine=innodb default charset utf8;

create table t_order_item(
	id bigint primary key auto_increment,
    produce_id bigint not null,
    price numeric(8,2),
    num int default 1,
    order_id bigint not null,
    foreign key(order_id) references t_order(id) on delete cascade
)engine=innodb default charset utf8;

实体类定义

一般查询订单详细信息时,需要加载对应的订单详情信息

public class OrderBean implements Serializable{
	private Long id;
	private Date orderDate; 
	private Double allPrice;
	private Set<OrderItemBean> items=new HashSet<>(0);  //0这个参数实际上含义在于避免不存储数据但是开辟空间,实际上JDK1.8中HashMap无参构建时已经使用了延迟初始化数组的处理,所以0不是必须的
}

订单详情类

public class OrderItemBean implements Serializable{
	private Long id;
	private Long produceId;
	private Double price;
	private Integer num;
}

定义映射元文件

如何实现获取订单信息时同时获取对应的订单详情信息?

方法1:

<mapper namespace="com.yan.mapper.OrderMapper">
    <resultMap id="baseResultMap" type="com.yan.entity.OrderBean">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="order_date" property="orderDate" jdbcType="TIMESTAMP"/>
        <result column="all_price" property="allPrice" jdbcType="NUMERIC"/>
    </resultMap>
    <resultMap id="extResultMap" extends="baseResultMap" type="com.yan.entity.OrderBean">
        <collection property="items" ofType="com.yan.entity.OrderItemBean" select="selectByOrderId" column="id"/>
    </resultMap>
    <select id="loadById" resultMap="extResultMap" parameterType="long">
        select * from t_order where id=#{id}
    </select>
    <select id="selectAll" resultMap="baseResultMap">
    	select * from t_order
    </select>
    <select id="selectByOrderId" resultType="com.yan.entity.OrderItemBean">
        select * from t_order_item where order_id=#{id}
	</select>
</mapper>

修改接口定义

public interface OrderMapper {
    OrderBean loadById(Long id);
    List<OrderItemBean> selectByOrderId(long id);
}

方法2:

    <resultMap id="baseResultMap" type="com.yan.entity.OrderBean">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <result column="order_date" property="orderDate" jdbcType="TIMESTAMP"/>
        <result column="all_price" property="allPrice" jdbcType="NUMERIC"/>
    </resultMap>
    <resultMap id="extResultMap" extends="baseResultMap" type="com.yan.entity.OrderBean">
        <collection property="items" ofType="com.yan.entity.OrderItemBean">
            <id column="item_id" property="id" jdbcType="BIGINT"/>
            <result column="produce_id" property="produceId" jdbcType="BIGINT"/>
            <result column="num" property="num" jdbcType="NUMERIC"/>
        </collection>
    </resultMap>
    <select id="loadById" resultMap="extResultMap" parameterType="long">
        select od.*,it.id item_id,it.produce_id,it.num from t_order od left join t_order_item it on od.id=it.order_id where od.id=#{id}
    </select>

###collection对多

  • select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果。

  • column:将主查询中列的结果作为嵌套查询的参数,配置方式如column="{prop1=col1,prop2=col2}",prop1和prop2将作为嵌套查询的参数。

  • fetchType:数据加载方式,可选值为lazy和eager,分别为延迟加载和积极加载。

  • 如果要使用延迟加载,除了将fetchType设置为lazy,还需要注意全局配置aggressiveLazyLoading的值应该为false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值