①日志
由于写代码的过程中,有很多时候需要输出调试信息,然后平时我们使用system.out.println的时候就会很麻烦,又不知道是哪个类出了问题、哪个线程出来的,也没办法把关闭调试信息,只能一条条删。
那么! 就有个第三方的日志工具Log4j(不是mybatis自带),开启日志! 知道执行了哪些sql语句,以便进行调试:
首先要准备一个log4j.properties,这里面是日志的配置信息,具体的语义在上一篇专门的log4j学习笔记里面写好啦,这里的具体语句作用也写在了代码注释上面!
# Global logging configuration
log4j.rootLogger=ERROR, stdout #产生日志的级别的ERROR,输出到stdout,这个stdout会设置
# MyBatis logging configuration...
log4j.logger.com.how2java=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender #stdout就是给他输出到控制台
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n #这是输出到控制台的格式,分别是 %5p 输出的优先级为5 %t是输出那个线程 %m是输出代码中指定的信息,也就是我们的sql,%n是换行
然后运行我们的测试类就可以看到效果:
里面有我们只想的sql语句,还有各种参数,不要太直白好吧!
②事务管理
之前咱也学过事务的概念。
就是处于同一事务的事情! 要么全都一起成功,要么全都失败,保持一个一致性。
要注意的是,数据库的类型必须的innodb的方式才会支持事务(之前用的myisam更快,但是不支持事务,也不支持外键)
开启innodb之后,执行这段代码:
由于事务的关系就会因为插入的第二段字符串太长了,导致插入的第一条数据也失败。这样就保证了数据的安全。(应该是session.commit之后才是这个事务的提交)
package com.how2java;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
public class TestMybatis {
public static void main(String[] args) throws IOException, SQLException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
CategoryMapper mapper = session.getMapper(CategoryMapper.class);
Category c1 = new Category();
c1.setName("长度够短的名称");
mapper.add(c1);
Category c2 = new Category();
c2.setName("超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称超过最大长度30的名称");
mapper.add(c2);
listAll(mapper);
session.commit();
session.close();
}
private static void listAll(CategoryMapper mapper) {
List<Category> cs = mapper.list();
for (Category c : cs) {
System.out.println(c.getName());
}
}
}
③延迟加载
就是昨天咱写的数据库一对多的情况的时候,是实现了category对product的一对多。
然后咱在查询category的时候,有时候并不会用上product集合,但是!mybatis也会给我们一并的把product加载了,这就会浪费资源。
所谓延迟加载呢,就是说我们查询category,ok,那么我就只把category给你处理好,只有当你在调用product对应的查询的时候才会去动product,节省了资源!
设置方法,在mybatis-config.xml中设置开启延迟加载:
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 将积极加载改为消息加载即按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
就行啦。
④分页
咱在之前写j2ee项目的时候也实现过,通过参数start和count,设置sql语句
select * from category_ limit start,count
就可以实现分页查询的功能。
那么mybatis里面也是这样。
xml方式:
在xml中把category的list方法改一下
改成:
<select id="listCategory" resultType="Category">
select * from category_
<if test="start!=null and count !=null">
limit #{start} , #{count}
</if>
</select>
然后在使用的时候用Map装一下参数params就行了。
注解方式:
这才是新学到的东西哈哈。
在CategoryMapper新加一个方法
@Select("select * from category_ limit #{start},#{count}")
public List<Category> listByPage(@Param("start") int start,@Param("count") int count);
用@param的方式传参,在使用的时候都不用map,直接传就行了。
⑤PAGEHELPER
在github上面的大佬写的 mybatis分页插件,分页的开发再也不用我们自己烦恼了。
在导入了包之后,
在mybatis-config.xml中加上一句:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
</plugin>
</plugins>
表示开启pagehelper插件
然后就只需要在执行查询的语句之前 加上一句:
PageHelper.offsetPage(0, 5);
就可以了,再调用查询语句就只会显示前五个了,和上一步分页中的效果是一样的。
还有功能就是 获取总数:
PageInfo pageInfo = new PageInfo<>(cs);
哈哈字面意思,分页的信息都在里面了,里面有获取总数啥的方法。
⑥一级缓存
就是在同一个sqlsession当中, 两次相同的查询不会再次去调用sql语句,而是在一级缓存中有查询结果了。
* 一级缓存失效情况(没有使用到当前一级缓存的情况,效果就是,还需要再向数据库发出查询):
* 1、sqlSession不同。
* 2、sqlSession相同,查询条件不同.(当前一级缓存中还没有这个数据)
* 3、sqlSession相同,两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响)
* 4、sqlSession相同,手动清除了一级缓存(缓存清空)
⑦二级缓存
相比一级缓存,二级缓存的范围要大点。在同一个SqlSessionFactory中,都不用重新调用sql了
在之前的 延迟加载的mybatis-config.xml中的settings中加上一句:
<setting name="cacheEnabled" value="true"/>
表示支持二级缓存
然后在Category.xml中增加 <cache/>,表示移动category对象的二级缓存
然后在pojo中的Category实现序列化接口
package com.how2java.pojo;
import java.io.Serializable;
import java.util.List;
public class Category implements Serializable{
private int id;
private String name;
List<Product> products;
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 List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
@Override
public String toString() {
return "Category [id=" + id + ", name=" + name + "]";
}
}
⑧单纯的MYBATIS整合C3P0数据库连接池
启动c3p0数据库连接池,在高并发的时候有性能优化。
需要的操作,导入jar包,然后新建一个C3P0DataSourceFactory类继承UnpooledDataSourceFactory,然后指定dataSource 为ComboPooledDataSource。
这个ComboPooledDataSource就是c3p0的数据源。
package org.mybatis.c3p0;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory{
public C3P0DataSourceFactory(){
this.dataSource =new ComboPooledDataSource();
}
}
然后在mybatis-config.xml中,把DataSource的type从POOLED改成type="org.mybatis.c3p0.C3P0DataSourceFactory"的数据源:
<?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>
<typeAliases>
<package name="com.how2java.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- <dataSource type="POOLED"> -->
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/> -->
<!-- <property name="url" value="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8"/> -->
<!-- <property name="username" value="root"/> -->
<!-- <property name="password" value="admin"/> -->
<!-- </dataSource> -->
<dataSource type="org.mybatis.c3p0.C3P0DataSourceFactory">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/how2java?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false"/>
<property name="user" value="root" />
<property name="password" value="admin" />
<!-- 连接池初始化大小为3 -->
<property name="initialPoolSize" value="3"/>
<!-- 连接池最大为10 -->
<property name="maxPoolSize" value="10"/>
<!-- 连接池最小为3 -->
<property name="minPoolSize" value="3"/>
<!-- 连接池在无空闲连接可用时一次性最多创建的新数据库连接数 -->
<property name="acquireIncrement" value="5"/>
<!-- 连接的最大空闲时间,如果超过这个时间(秒),某个数据库连接还没有被使用,则会断开掉这个连接。如果为0,则永远不会断开连接,即回收此连接 -->
<property name="maxIdleTime" value="30"/>
<!-- 最大的Statement数量 -->
<property name="maxStatements" value="500"/>
<!-- 每个连接启动的最大Statement数量 -->
<property name="maxStatementsPerConnection" value="50"/>
<!-- 同时运行的线程数 -->
<property name="numHelperThreads" value="5"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/how2java/pojo/Category.xml"/>
</mappers>
</configuration>
c3p0就能顺利运行了,在高并发的情况下能体现其性能优势。
⑨逆向工程
之前学习都是先吧pojo、mapper、xml写好了,然后去创建对应的表结构,而逆向工程的方式,就是在我们数据库中创建好了表的前提下,逆向的帮我们把pojo、mapper、xml创建出来。
这样就很方便了,还不用自己去写CRUD那些sql语句,提高效率,减少出错。
配置过程:
先导入包,然后在src目录下面创建一个generatorConfig.xml文件,
这个文件要做的事情有:
1、设置数据库连接的账号密码
2、指定pojo、mapper、xml生成的包名
3、指定表名以及表名对应的类名
4、使用自增长键
<property name="my.isgen.usekeys" value="true"/>
<generatedKey column="id" sqlStatement="JDBC"/>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--数据库驱动-->
<!--
如果IDE(eclipse或者idea) 项目里导入了jar包,那么就不需要配置了jar包的绝对路径了
<classPathEntry location="e:/project/mybatis/lib/mysql-connector-java-5.0.8-bin.jar"/>
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="false"/>
</commentGenerator>
<!--数据库链接地址账号密码-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost/how2java" userId="root" password="admin">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--生成Model类存放位置-->
<javaModelGenerator targetPackage="com.how2java.pojo" targetProject="src">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--生成映射文件存放位置-->
<sqlMapGenerator targetPackage="com.how2java.pojo" targetProject="src">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成Dao类存放位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.how2java.mapper" targetProject="src">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--生成对应表及类名-->
<table tableName="category_" domainObjectName="Category" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
<property name="my.isgen.usekeys" value="true"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<!-- <table tableName="product_" domainObjectName="Product" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> -->
</context>
</generatorConfiguration>
然后运行:
package com.how2java;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class TestMybatisGenerator {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
InputStream is= TestMybatisGenerator.class.getClassLoader().getResource("generatorConfig.xml").openStream();
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(is);
is.close();
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
System.out.println("生成代码成功,刷新项目,查看文件,然后执行TestMybatis.java");
}
}
这样就生成好了对应东西啦,但是要注意的是:
1、
2、
mybatis-config.xml需要自己创建
3、
在查询的时候需要借助CategoryExample查询
比如执行一次模糊查询:
package com.how2java;
import java.io.InputStream;
import java.util.List;
//import com.how2java.mapper.CategoryMapper;
//import com.how2java.pojo.Category;
//import com.how2java.pojo.CategoryExample;
//import com.how2java.mapper.CategoryMapper;
//import com.how2java.pojo.CategoryExample;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
import com.how2java.pojo.CategoryExample;
public class TestMybatis {
public static void main(String args[]) throws Exception {
System.out.println("先运行TestMybatisGenerator创建mapper,pojo,xml 等文件,然后取消import里被注释的,以及接下来的注释,并执行代码");
//
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session=sqlSessionFactory.openSession();
CategoryExample example = new CategoryExample();
example.createCriteria().andNameLike("%9%");
CategoryMapper mapper = session.getMapper(CategoryMapper.class);
List<Category> cs= mapper.selectByExample(example);
for (Category c : cs) {
System.out.println(c.getName());
}
}
}
mybatis的内容告一段落哈哈哈,明天整新知识啦。