mybatis

持久层框架,半自动ORM框架

在jsp中引入资源文件路径

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
然后在basePath后面跟路径,不带/
<%=basePath%>......

jdbc连接数据库的方式

/*
 * JDBC操作数据库的步骤:
 * 1.注册驱动
 *      告知JVM使用的是哪一个数据库的驱动
 * 2.获得连接
 *      使用JDBC中的类,完成对mysql数据库的连接(TCP协议)
 * 3.获得语句执行平台
 *      通过连接对象获取对SQL语句的执行者对象
 * 4.执行sql语句
 *      使用执行者对象,向数据库执行SQL语句
 *      获取数据库的执行后的结果
 * 5.处理结果
 * 6.释放资源
 *      调用一堆close
 */
public class JDBCTest {
 
    public static void main(String[] args) throws Exception {
 
        public static void main(String[] args) throws Exception {
        // 1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.获取连接对象
        String url = "jdbc:mysql://localhost:3306/itheima";
        Connection conn = DriverManager.getConnection(url, "root", "root");
        
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String user = sc.nextLine();
        System.out.println("请输入密码:");
        String pass = sc.nextLine();
        // 拼写SQL语句
        String sql = "select * from users where username = ? and password = ? ";
        // 3.获取执行SQL语句
        //Connection接口
        PreparedStatement pst = conn.prepareStatement(sql);
        //调用pst对象的setXXX方法设置问号占位符的参数
        pst.setObject(1, user);
        pst.setObject(2, pass);
        System.out.println(sql);
        // 4.调用执行者对象方法,执行SQL语句获取结果集
        ResultSet rs = pst.executeQuery();
        // 5.处理结果集
        while (rs.next()) {
            System.out.println(rs.getString("username") + "\t" + rs.getString("password"));
        }
        // 6.关闭资源
        rs.close();
        pst.close();
        conn.close();

}
}

使用mybatis

1引入jar包
2配置mybatis
<?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>
    <!-- mybatis的环境配置,此信息在开发中只需照搬即可 -->
    <environments default="development">
        <environment id="development">
            <!-- 配置JDBC事务,此事务由mybatis管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置连接池,此连接池为mybatis连接池 -->
            <dataSource type="POOLED">
                <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="root"/>
            </dataSource>
        </environment>
    </environments>
    
    <!-- 映射文件 (加载所需要的局部配置)
    Mappers
        <mapper resource=’’/>
        使用相对于类路径的资源
        如:<mapper resource="sqlmap/User.xml" />
        <mapper url=’’/>
                     使用完全限定路径
        如:<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />
        <mapper class=’’/>
        使用mapper接口的全限定名
        如:<mapper class="com.sjg.dao.UserMapper"/>
        注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
        
        <package name=’’/>(推荐)
        注册指定包下的所有映射文件
        如:<package name="com.sjg.dao"/>
        注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下;
    -->
    <mappers>
        <mapper resource="config/User.xml"/>
        <package name="com.sjg.dao"/>
    </mappers>
</configuration>

mybatis的核心对象SqlSession

1:向sql语句传递参数
2:执行sql语句
3:获取执行sql语句的结果
4:事务的控制

如何拿到SqlSession

1:通过配置文件获取数据库连接信息
2:通过配置信息构建SqlSessionFactory
3:通过SqlSessionFactory打开数据库连接会话SqlSession

public static void main(String[] args) {
        String resource = "config/mybatis-config.xml";
           InputStream inputStream = Resources.getResourceAsStream(resource);
            // 构建sqlSession工厂
            SqlSessionFactory sqlSessionFactory = new     
            SqlSessionFactoryBuilder().build(inputStream);
            // 获取sqlSession
            SqlSession    session = sqlSessionFactory.openSession();
                  
    }

mybatis的mapper文件

<?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.atguigu.crud.dao.EmployeeMapper">
 //配置数据库对应的Java类型
  <resultMap type="com.atguigu.crud.bean.Employee" id="WithDeptResultMap">
    <id column="emp_id" jdbcType="INTEGER" property="empId" />
    <result column="emp_name" jdbcType="VARCHAR" property="empName" />
    <result column="gender" jdbcType="CHAR" property="gender" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="d_id" jdbcType="INTEGER" property="dId" />
    <!-- 指定联合查询出的部门字段的封装 -->
    <association property="department" javaType="com.atguigu.crud.bean.Department">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </association>
  </resultMap>
  <sql id="columns">    emp_id, emp_name, gender, email, d_id
</sql>
// parameterType为接受参数类型
  <select id="queryMessageList" parameterType="com.atguigu.crud.bean.Employee" resultMap="WithDeptResultMap">
    select <include refid="columns"/> from MESSAGE
    <where>
        <if test="empId!= null and !&quot;&quot;.equals(empId.trim())">
            and COMMAND=#{command}
        </if>
        <if test="empName!= null and !&quot;&quot;.equals(empName.trim())">
            and DESCRIPTION like '%' #{empName} '%'
        </if>
    </where>
  </select>
  

  <delete id="deleteOne" parameterType="int">
    delete from MESSAGE where ID = #{_parameter}
  </delete>
  
  <delete id="deleteBatch" parameterType="java.util.List">
    delete from MESSAGE where ID in(
        <foreach collection="list" item="item" separator=",">
            #{item}
        </foreach>
    )
  </delete>
</mapper>

使用sqlSession:

例如
sqlSession.selectList("mapper+id");
传参
sqlSession.selectList("mapper+id",conmand);

mybatis中ognl表达式

image.png
java常用操作符有的需要转义
image.png

mybatis调试log4j整合

引入log4j的jar包
配置log4j

输出日志的级别和位置
log4j.rootLogger=DEBUG,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.org.apache=INFO

在mybatis.xml中,指定使用log4j为日志实现,
<?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>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
</configuration>
这里的value值可以是SLF4J、Apache Commons Logging、Log4J2、Log4J、JDK logging(除Log4J2、Log4J外,其他未验证),并会按顺序查找

在web.xml中也需要配置======
<listener>
     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
 </listener>

mybatis对于增删改(和数据库引擎有关)
需要sqlSession.comimt();提交

一对多

<mapper namespace="Command">
  <resultMap type="com.imooc.bean.Command" id="Command">
    <id column="C_ID" jdbcType="INTEGER" property="id"/>
    <result column="NAME" jdbcType="VARCHAR" property="name"/>
    <result column="DESCRIPTION" jdbcType="VARCHAR" property="description"/>
    <collection property="contentList"  resultMap="CommandContent.Content"/>
  </resultMap>
  
  <select id="queryCommandList" parameterType="com.imooc.bean.Command" resultMap="Command">
    select a.ID C_ID,a.NAME,a.DESCRIPTION,b.ID,b.CONTENT,b.COMMAND_ID
    from COMMAND a left join COMMAND_CONTENT b
    on a.ID=b.COMMAND_ID
    <where>
        <if test="name != null and !&quot;&quot;.equals(name.trim())">
            and a.NAME=#{name}
        </if>
        <if test="description != null and !&quot;&quot;.equals(description.trim())">
            and a.DESCRIPTION like '%' #{description} '%'
        </if>
    </where>
  </select>
</mapper>

常用标签

image.png

MyBatis 获取数据库中自增主键值

<!-- 
        useGeneratedKeys 设置为 true
        keyProperty 表示把获得的自增主键的值赋给 javabean 中的哪个属性,
        这里表示赋值给 employee 的 id 属性
    -->
    <insert id="addEmp" parameterType="employee" 
            useGeneratedKeys="true" keyProperty="id">
        insert into t_employee(username, gender, email) values (#{username}, #{gender}, #{email})
    </insert>

mybatis接口式编程

1:mybatis的mapper文件的namespace属性和代理接口的包名+接口名一样
2:方法名与mapper文件的id,传入参数,返回值类型一样

mybatis调用接口(底层通过动态代理)
//获得代理的实例
IMessage imessage = sqlSession.getMapper(IMessage.class//接口);
messageList = imessage.queryMessageList(parameter);

配置mybatis分页拦截器

配置文件中配置plugin
 <plugins>
    <plugin interceptor="com.imooc.interceptor.PageInterceptor">
        <property name="test" value="abc"/>
    </plugin>
  </plugins>

/**
 * 分页拦截器
 */
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})
public class PageInterceptor implements Interceptor {
    
    private String test;
    // 这里是每次执行操作的时候,都会进行这个拦截器的方法内
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY);
        MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
        // 配置文件中SQL语句的ID
        String id = mappedStatement.getId();
        if(id.matches(".+ByPage$")) {
            BoundSql boundSql = statementHandler.getBoundSql();
            // 原始的SQL语句
            String sql = boundSql.getSql();
            // 查询总条数的SQL语句
            String countSql = "select count(*) from (" + sql + ")a";
            Connection connection = (Connection)invocation.getArgs()[0];
            PreparedStatement countStatement = connection.prepareStatement(countSql);
            ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");
            parameterHandler.setParameters(countStatement);
            ResultSet rs = countStatement.executeQuery();
            
            Map<?,?> parameter = (Map<?,?>)boundSql.getParameterObject();
            Page page = (Page)parameter.get("page");
            if(rs.next()) {
                page.setTotalNumber(rs.getInt(1));
            }
            // 改造后带分页查询的SQL语句
            String pageSql = sql + " limit " + page.getDbIndex() + "," + page.getDbNumber();
            metaObject.setValue("delegate.boundSql.sql", pageSql);
        }
        return invocation.proceed();
    }
         // 主要是为了把这个拦截器生成一个代理放到拦截器链中(拦截进行过滤)
    @Override
    public Object plugin(Object target) {
        System.out.println(this.test);
        return Plugin.wrap(target, this);
    }
        //拿到配置文件里面的值
    @Override
    public void setProperties(Properties properties) {
        this.test = properties.getProperty("test");
        // TODO Auto-generated method stub
        
    }

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容