Mybatis框架篇

2017-01-13 15:06:05来源:csdn作者:sinat_33949861人点击

第七城市


1Mybatis入门
1.2MyBatis介绍

MyBatis 本是apache的一个开源项目iBatis,
2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,再后来,托管到github下,实质上Mybatis对ibatis进行一些改进。


MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。


Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。


1.3Mybatis架构

1、 mybatis配置


SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。


mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。


2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂


3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。


4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。


5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。


6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。


7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

1.4mybatis下载

mybaits的代码由github.com管理,地址:https://github.com/mybatis/mybatis-3/releases

mybatis-3.2.7.jar----mybatis的核心包


lib----mybatis的依赖包


mybatis-3.2.7.pdf----mybatis使用手册

1.5创建mysql数据库

先导入sql_table.sql,再导入 sql_data.sql脚本:

如下:


1.6Mybatis入门程序1.6.1 需求

实现以下功能:


根据用户id查询一个用户信息


根据用户名称模糊查询用户信息列表


添加用户


更新用户


删除用户

1.6.2 第一步:创建java工程

使用eclipse创建java工程,jdk使用1.7.0_72。


1.6.3 第二步:加入jar包

加入mybatis核心包、依赖包、数据驱动包。

1.6.4 第三步:log4j.properties

在classpath下创建log4j.properties如下:

# Global loggingconfiguration


log4j.rootLogger=DEBUG, stdout


# Console output...


log4j.appender.stdout=org.apache.log4j.ConsoleAppender


log4j.appender.stdout.layout=org.apache.log4j.PatternLayout


log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

mybatis默认使用log4j作为输出日志信息。

1.6.5 第四步:SqlMapConfig.xml

在classpath下创建SqlMapConfig.xml,如下:

<?xmlversion="1.0"encoding="UTF-8"?>


<!DOCTYPEconfiguration


PUBLIC"-//mybatis.org//DTDConfig 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>



<!--和spring整合后
environments配置将废除-->



<environmentsdefault="development">


<environmentid="development">


<!--使用jdbc事务管理-->


<transactionManagertype="JDBC"/>


<!--数据库连接池-->


<dataSourcetype="POOLED">


<propertyname="driver"value="com.mysql.jdbc.Driver"/>


<propertyname="url"value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>


<propertyname="username"value="root"/>


<propertyname="password"value="mysql"/>


</dataSource>


</environment>



</environments>




</configuration>

SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。


1.6.6 第五步:po类

Po类作为mybatis进行sql映射使用,po类通常与数据库表对应,User.java如下:

Public class User {



private intid;



private String
username;//用户姓名



private String
sex;//性别



private Date
birthday;//生日



private String
address;//地址


get/set……

1.6.7 第六步:程序编写
1.6.7.1 查询1.6.7.1.1映射文件:

在classpath下的sqlmap目录下创建sql映射文件Users.xml:

<?xmlversion="1.0"encoding="UTF-8"?>


<!DOCTYPEmapper


PUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mappernamespace="test">


</mapper>

namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。


在SqlMapConfig.xml中添加:


<!--根据id获取用户信息 -->



<select id="findUserById"parameterType="int"resultType="cn.itcast.mybatis.po.User">


select * from user where id = #{id}



</select>



<!-- 自定义条件查询用户列表 -->



<selectid="findUserByUsername"parameterType="java.lang.String"



resultType="cn.itcast.mybatis.po.User">



select * from user whereusername like '%${value}%'



</select>



parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。


resultType:定义结果映射类型。

1.6.7.1.2加载映射文件

mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml,如下:

<mappers>


<mapper
resource="sqlmap/User.xml"/>


</mappers>


1.6.7.1.3测试程序:

publicclass Mybatis_first {





//会话工厂



private SqlSessionFactorysqlSessionFactory;




@Before



publicvoid createSqlSessionFactory()throws IOException {


//
配置文件


String resource =
"SqlMapConfig.xml";


InputStream inputStream = Resources.getResourceAsStream(resource);



//
使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory


sqlSessionFactory =new SqlSessionFactoryBuilder()


.build(inputStream);




}




// 根据 id查询用户信息



@Test



publicvoidtestFindUserById() {


//
数据库会话实例


SqlSessionsqlSession =
null;


try {


//
创建数据库会话实例sqlSession


sqlSession=
sqlSessionFactory.openSession();


//
查询单个记录,根据用户id查询用户信息


Useruser = sqlSession.selectOne("test.findUserById", 10);


//
输出用户信息


System.out.println(user);


}catch(Exception e) {


e.printStackTrace();


}finally{


if (sqlSession !=null) {


sqlSession.close();


}


}




}




// 根据用户名称模糊查询用户信息



@Test



publicvoidtestFindUserByUsername() {


//
数据库会话实例


SqlSessionsqlSession =
null;


try {


//
创建数据库会话实例sqlSession


sqlSession=
sqlSessionFactory.openSession();


//
查询单个记录,根据用户id查询用户信息


List<User>list = sqlSession.selectList("test.findUserByUsername","张");


System.out.println(list.size());


}catch(Exception e) {


e.printStackTrace();


}finally{


if (sqlSession !=null) {


sqlSession.close();


}


}




}


}

1.6.7.1.4#{}和${}

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。
#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。


1.6.7.1.5parameterType和resultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。


resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

1.6.7.1.6selectOne和selectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:


org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned byselectOne(), but found: 3


atorg.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

selectList可以查询一条或多条记录。

1.6.7.2 添加
1.6.7.2.1映射文件:

在SqlMapConfig.xml中添加:


<!--添加用户 -->



<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User">



<selectKeykeyProperty="id"order="AFTER"resultType="java.lang.Integer">


select LAST_INSERT_ID()



</selectKey>



insert into user(username,birthday,sex,address)



values(#{username},#{birthday},#{sex},#{address})


</insert>

1.6.7.2.2测试程序:

//添加用户信息



@Test



publicvoid testInsert() {


//
数据库会话实例


SqlSession sqlSession =
null;


try {


//
创建数据库会话实例sqlSession


sqlSession =
sqlSessionFactory.openSession();


//
添加用户信息


User user =
new User();


user.setUsername("张小明");


user.setAddress("河南郑州");


user.setSex("1");


user.setPrice(1999.9f);


sqlSession.insert("test.insertUser", user);


//提交事务


sqlSession.commit();


}
catch (Exception e) {


e.printStackTrace();


}
finally {


if (sqlSession !=null) {


sqlSession.close();


}


}


}


1.6.7.2.3mysql自增主键返回

通过修改sql映射文件,可以将mysql自增主键返回:


<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User">


<!-- selectKey将主键返回,需要再返回 -->


<selectKey
keyProperty="id"order="AFTER"resultType="java.lang.Integer">


select LAST_INSERT_ID()


</selectKey>



insert into user(username,birthday,sex,address)



values(#{username},#{birthday},#{sex},#{address});


</insert>


添加selectKey实现将主键返回


keyProperty:返回的主键存储在pojo中的哪个属性


order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after


resultType:返回的主键是什么类型


LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

1.6.7.2.4Mysql使用 uuid实现主键

需要增加通过select uuid()得到uuid值

<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User">


<selectKeyresultType="java.lang.String" order="BEFORE"


keyProperty="id">


select uuid()


</selectKey>


insert into user(id,username,birthday,sex,address)


values(#{id},#{username},#{birthday},#{sex},#{address})


</insert>


注意这里使用的order是“BEFORE”


1.6.7.2.5Oracle使用序列生成主键

首先自定义一个序列且用于生成主键,selectKey使用如下:


<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User">


<selectKeyresultType="java.lang.Integer" order="BEFORE"


keyProperty="id">


SELECT 自定义序列.NEXTVAL FROM DUAL


</selectKey>


insert into user(id,username,birthday,sex,address)


values(#{id},#{username},#{birthday},#{sex},#{address})


</insert>


注意这里使用的order是“BEFORE”


1.6.7.3 删除
1.6.7.3.1映射文件:

<!--删除用户 -->



<deleteid="deleteUserById"parameterType="int">


delete from user where id=#{id}


</delete>


1.6.7.3.2测试程序:

//根据id删除用户



@Test



publicvoidtestDelete() {


//
数据库会话实例


SqlSession sqlSession =
null;


try {


//
创建数据库会话实例sqlSession


sqlSession =
sqlSessionFactory.openSession();


//
删除用户


sqlSession.delete("test.deleteUserById",18);


//
提交事务


sqlSession.commit();


}
catch (Exception e) {


e.printStackTrace();


}
finally {


if (sqlSession !=null) {


sqlSession.close();


}


}


}


1.6.7.4 修改
1.6.7.4.1映射文件

<!--更新用户 -->



<updateid="updateUser"parameterType="cn.itcast.mybatis.po.User">


update user set
username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}


where id=#{id}


</update>

1.6.7.4.2测试程序

//更新用户信息



@Test



publicvoidtestUpdate() {


//
数据库会话实例


SqlSession sqlSession =
null;


try {


//
创建数据库会话实例sqlSession


sqlSession =
sqlSessionFactory.openSession();


//
添加用户信息


User user =
new User();


user.setId(16);


user.setUsername("张小明");


user.setAddress("河南郑州");


user.setSex("1");


user.setPrice(1999.9f);


sqlSession.update("test.updateUser", user);


//
提交事务


sqlSession.commit();



}
catch (Exception e) {


e.printStackTrace();


}
finally {


if (sqlSession !=null) {


sqlSession.close();


}


}


}


1.6.8 Mybatis解决jdbc编程的问题
1.6.9 与hibernate不同

Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。


总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。


2Dao开发方法

使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法。

2.0需求

将下边的功能实现Dao:


根据用户id查询一个用户信息


根据用户名称模糊查询用户信息列表


添加用户信息

2.1SqlSession的使用范围

SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。


通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。

2.1.0 SqlSessionFactoryBuilder

SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

2.1.1 SqlSessionFactory

SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

2.1.2 SqlSession

SqlSession是一个面向用户的接口,sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。

执行过程如下:


1、 加载数据源等配置信息


Environment environment = configuration.getEnvironment();


2、 创建数据库链接


3、 创建事务对象


4、 创建Executor,SqlSession所有操作都是通过Executor完成,mybatis源码如下:

if (ExecutorType.BATCH == executorType) {


executor =
newBatchExecutor(this,
transaction);



} elseif (ExecutorType.REUSE == executorType){


executor =
new ReuseExecutor(this, transaction);



} else {


executor =
new SimpleExecutor(this, transaction);



}


if (cacheEnabled) {


executor =
newCachingExecutor(executor, autoCommit);


}

5、 SqlSession的实现类即DefaultSqlSession,此对象中对操作数据库实质上用的是Executor

结论:


每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。


打开一个SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:


SqlSession session = sqlSessionFactory.openSession();


try {


// do work


} finally {


session.close();


}


2.2原始Dao开发方式

原始Dao开发方法需要程序员编写Dao接口和Dao实现类。


2.2.0 映射文件

<?xmlversion="1.0"encoding="UTF-8"?>


<!DOCTYPEmapper


PUBLIC"-//mybatis.org//DTD Mapper 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mappernamespace="test">


<!--根据id获取用户信息 -->



<select id="findUserById"parameterType="int"resultType="cn.itcast.mybatis.po.User">


select * from user where id = #{id}


</select>


<!--添加用户 -->



<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User">



<selectKeykeyProperty="id"order="AFTER"resultType="java.lang.Integer">


selectLAST_INSERT_ID()



</selectKey>



insert into user(username,birthday,sex,address)



values(#{username},#{birthday},#{sex},#{address})


</insert>


</mapper>


2.2.1 Dao接口

Public interface UserDao {



public User getUserById(int id)throws Exception;



public void insertUser(User user)throws Exception;


}

Public class UserDaoImplimplements UserDao {





//注入SqlSessionFactory



public UserDaoImpl(SqlSessionFactory sqlSessionFactory){


this.setSqlSessionFactory(sqlSessionFactory);



}





private SqlSessionFactorysqlSessionFactory;



@Override



public User getUserById(int id)throws Exception {


SqlSession session =
sqlSessionFactory.openSession();


User user =
null;


try {


//通过sqlsession调用selectOne方法获取一条结果集


//参数1:指定定义的statement的id,参数2:指定向statement中传递的参数


user = session.selectOne("test.findUserById", 1);


System.out.println(user);



}
finally{


session.close();


}


return user;



}





@Override



Public void insertUser(User user)throws Exception {


SqlSession
sqlSession=sqlSessionFactory.openSession();


try {


sqlSession.insert("insertUser", user);


sqlSession.commit();


}
finally{


session.close();


}




}


}

2.2.2 问题2.3Mapper动态代理方式
2.3.0 实现原理

Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。


Mapper接口开发需要遵循以下规范:


1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。


2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同


3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同


4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同


2.3.1Mapper.xml(映射文件)

定义mapper映射文件UserMapper.xml(内容同Users.xml),需要修改namespace的值为 UserMapper接口路径。将UserMapper.xml放在classpath 下mapper目录下。

<?xmlversion="1.0"encoding="UTF-8"?>


<!DOCTYPEmapper


PUBLIC"-//mybatis.org//DTDMapper 3.0//EN"


"http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mappernamespace="cn.itcast.mybatis.mapper.UserMapper">


<!--根据id获取用户信息 -->



<select id="findUserById"parameterType="int"resultType="cn.itcast.mybatis.po.User">


select * from user where id = #{id}


</select>


<!--自定义条件查询用户列表 -->



<selectid="findUserByUsername"parameterType="java.lang.String"



resultType="cn.itcast.mybatis.po.User">



select * from user whereusername like '%${value}%'


</select>


<!--添加用户 -->



<insertid="insertUser"parameterType="cn.itcast.mybatis.po.User">



<selectKeykeyProperty="id"order="AFTER"resultType="java.lang.Integer">


select LAST_INSERT_ID()



</selectKey>



insert into user(username,birthday,sex,address)



values(#{username},#{birthday},#{sex},#{address})


</insert>

</mapper>

2.3.2Mapper.java(接口文件)

/**


*用户管理mapper


*/


Public interface UserMapper {



//根据用户id查询用户信息



public User findUserById(int id)throws Exception;



//查询用户列表



public List<User> findUserByUsername(String username)throws Exception;



//添加用户信息



publicvoid insertUser(User user)throws Exception;


}

接口定义有如下特点:


1、 Mapper接口方法名和Mapper.xml中定义的statement的id相同


2、 Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同


3、 Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同

2.3.3 加载UserMapper.xml文件

修改SqlMapConfig.xml文件:

<!--加载映射文件 -->


<mappers>


<mapperresource="mapper/UserMapper.xml"/>


</mappers>


2.3.4 测试

Public class UserMapperTestextends TestCase {




private SqlSessionFactorysqlSessionFactory;





protected void setUp()throws Exception {


//mybatis配置文件


String resource =
"sqlMapConfig.xml";


InputStream inputStream = Resources.getResourceAsStream(resource);


//使用SqlSessionFactoryBuilder创建sessionFactory


sqlSessionFactory =new
SqlSessionFactoryBuilder().build(inputStream);



}






Public void testFindUserById()throws Exception {


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获取mapper接口的代理对象


UserMapper userMapper = session.getMapper(UserMapper.class);


//调用代理对象方法


User user = userMapper.findUserById(1);


System.out.println(user);


//关闭session


session.close();




}


@Test



publicvoid testFindUserByUsername()throws Exception {


SqlSession sqlSession =
sqlSessionFactory.openSession();


UserMapper userMapper = sqlSession.getMapper(UserMapper.class);


List<User> list = userMapper.findUserByUsername("张");


System.out.println(list.size());




}


Public void testInsertUser()throws Exception {


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获取mapper接口的代理对象


UserMapper userMapper = session.getMapper(UserMapper.class);


//要添加的数据


User user =
new User();


user.setUsername("张三");


user.setBirthday(new Date());


user.setSex("1");


user.setAddress("北京市");


//通过mapper接口添加用户


userMapper.insertUser(user);


//提交


session.commit();


//关闭session


session.close();



}





}

2.3.5 总结

uselectOne和selectList


动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

unamespace


mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。


3SqlMapConfig.xml配置文件
3.0配置内容

SqlMapConfig.xml中配置的内容和顺序如下:

properties(属性)


settings(全局配置参数)


typeAliases(类型别名)


typeHandlers(类型处理器)


objectFactory(对象工厂)


plugins(插件)


environments(环境集合属性对象)


environment(环境子属性对象)


transactionManager(事务管理)


dataSource(数据源)


mappers(映射器)

3.1properties(属性)

SqlMapConfig.xml可以引用java属性文件中的配置信息如下:

在classpath下定义db.properties文件,


jdbc.driver=com.mysql.jdbc.Driver


jdbc.url=jdbc:mysql://localhost:3306/mybatis


jdbc.username=root


jdbc.password=mysql


SqlMapConfig.xml引用如下:

<propertiesresource="db.properties"/>



<environments
default="development">


<environment
id="development">


<transactionManagertype="JDBC"/>


<dataSource
type="POOLED">


<property
name="driver"value="${jdbc.driver}"/>


<property
name="url"value="${jdbc.url}"/>


<property
name="username"value="${jdbc.username}"/>


<property
name="password"value="${jdbc.password}"/>


</dataSource>


</environment>


</environments>

注意: MyBatis 将按照下面的顺序来加载属性:


u在properties元素体内定义的属性首先被读取。


u然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。


u最后读取parameterType传递的属性,它会覆盖已读取的同名属性。

因此,通过parameterType传递的属性具有最高优先级,resource或 url 加载的属性次之,最低优先级的是 properties 元素体内定义的属性。


3.2settings(配置)
3.3typeAliases(类型别名)
3.3.0 mybatis支持别名:




















































































别名



映射的类型



_byte



byte



_long



long



_short



short



_int



int



_integer



int



_double



double



_float



float



_boolean



boolean



string



String



byte



Byte



long



Long



short



Short



int



Integer



integer



Integer



double



Double



float



Float



boolean



Boolean



date



Date



decimal



BigDecimal



bigdecimal



BigDecimal



3.3.1 自定义别名:

在SqlMapConfig.xml中配置:


<typeAliases>



<!-- 单个别名定义 -->



<typeAlias alias="user"type="cn.itcast.mybatis.po.User"/>



<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->



<packagename="cn.itcast.mybatis.po"/>



<package name="其它包"/>


</typeAliases>


3.4typeHandlers(类型处理器)

类型处理器用于java类型和jdbc类型映射,如下:

<selectid="findUserById"parameterType="int"resultType="user">


select * from user where id = #{id}


</select>

mybatis自带的类型处理器基本上满足日常需求,不需要单独定义。

mybatis支持类型处理器:




















































































































类型处理器



Java类型



JDBC类型



BooleanTypeHandler



Boolean,boolean



任何兼容的布尔值



ByteTypeHandler



Byte,byte



任何兼容的数字或字节类型



ShortTypeHandler



Short,short



任何兼容的数字或短整型



IntegerTypeHandler



Integer,int



任何兼容的数字和整型



LongTypeHandler



Long,long



任何兼容的数字或长整型



FloatTypeHandler



Float,float



任何兼容的数字或单精度浮点型



DoubleTypeHandler



Double,double



任何兼容的数字或双精度浮点型



BigDecimalTypeHandler



BigDecimal



任何兼容的数字或十进制小数类型



StringTypeHandler



String



CHAR和VARCHAR类型



ClobTypeHandler



String



CLOB和LONGVARCHAR类型



NStringTypeHandler



String



NVARCHAR和NCHAR类型



NClobTypeHandler



String



NCLOB类型



ByteArrayTypeHandler



byte[]



任何兼容的字节流类型



BlobTypeHandler



byte[]



BLOB和LONGVARBINARY类型



DateTypeHandler



Date(java.util)



TIMESTAMP类型



DateOnlyTypeHandler



Date(java.util)



DATE类型



TimeOnlyTypeHandler



Date(java.util)



TIME类型



SqlTimestampTypeHandler



Timestamp(java.sql)



TIMESTAMP类型



SqlDateTypeHandler



Date(java.sql)



DATE类型



SqlTimeTypeHandler



Time(java.sql)



TIME类型



ObjectTypeHandler



任意



其他或未指定类型



EnumTypeHandler



Enumeration类型



VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。


3.5mappers(映射器)

Mapper配置的几种方法:


3.5.0 <mapper resource="" />

使用相对于类路径的资源


如:<mapper resource="sqlmap/User.xml" />

3.5.1 <mapper url="" />

使用完全限定路径


如:<mapperurl="file:///D:/workspace_spingmvc/mybatis_01/config/sqlmap/User.xml"/>

3.5.2 <mapper class="" />

使用mapper接口类路径


如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

3.5.3 <package name=""/>

注册指定包下的所有mapper接口


如:<package name="cn.itcast.mybatis.mapper"/>


注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。


4Mapper.xml映射文件

Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。

4.0parameterType(输入类型)
4.0.0#{}与${}

#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?。

<!--根据id查询用户信息 -->



<select id="findUserById"parameterType="int"resultType="user">


select * from user where id = #{id}


</select>


使用占位符#{}可以有效防止sql注入,在使用时不需要关心参数值的类型,mybatis会自动进行java类型和jdbc类型的转换。#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

${}和#{}不同,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。使用${}不能防止sql注入,但是有时用${}会非常方便,如下的例子:

<!--根据名称模糊查询用户信息 -->



<select id="selectUserByName"parameterType="string"resultType="user">



select * from user whereusername like '%${value}%'


</select>

如果本例子使用#{}则传入的字符串中必须有%号,而%是人为拼接在参数中,显然有点麻烦,如果采用${}在sql中拼接为%的方式则在调用mapper接口传递参数就方便很多。

//如果使用占位符号则必须人为在传参数中加%


List<User> list= userMapper.selectUserByName("%管理员%");


//如果使用${}原始符号则不用人为在参数中加%


List<User>list= userMapper.selectUserByName("管理员");

再比如order by排序,如果将列名通过参数传入sql,根据传的列名进行排序,应该写为:


ORDER BY ${columnName}


如果使用#{}将无法实现此功能。


4.0.1传递简单类型

参考上边的例子。


4.0.2传递pojo对象

Mybatis使用ognl表达式解析对象字段的值,如下例子:

<!—传递pojo对象综合查询用户信息 -->



<select id="findUserByUser"parameterType="user"resultType="user">



select * from user whereid=#{id} and usernamelike '%${username}%'


</select>

上边红色标注的是user对象中的字段名称。

测试:

Public void testFindUserByUser()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//构造查询条件user对象



User user = new User();


user.setId(1);


user.setUsername("管理员");


//传递user对象查询用户列表


List<User>list = userMapper.findUserByUser(user);


//关闭session


session.close();


}

异常测试:

Sql中字段名输入错误后测试,username输入dusername测试结果报错:

org.apache.ibatis.exceptions.PersistenceException:


### Error querying database. Cause:org.apache.ibatis.reflection.ReflectionException:Thereis no getter for property named 'dusername' in 'classcn.itcast.mybatis.po.User'


### Cause: org.apache.ibatis.reflection.ReflectionException:There is no getter for property named 'dusername' in 'classcn.itcast.mybatis.po.User'

4.0.3 传递pojo包装对象

开发中通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。

4.0.3.0 定义包装对象

定义包装对象将查询条件(pojo)以类组合的方式包装起来。

publicclass QueryVo {





private User
user;





//自定义用户扩展类


private UserCustomuserCustom;


4.0.3.1 mapper.xml映射文件

说明:mybatis底层通过ognl从pojo中获取属性值:#{user.username},user即是传入的包装对象的属性。queryVo是别名,即上边定义的包装对象类型。


4.0.4传递hashmap

Sql映射文件定义如下:


<!--传递hashmap综合查询用户信息 -->



<select id="findUserByHashmap"parameterType="hashmap"resultType="user">



select * from user whereid=#{id} and usernamelike '%${username}%'


</select>

上边红色标注的是hashmap的key。

测试:


Public void testFindUserByHashmap()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//构造查询条件Hashmap对象


HashMap<String, Object> map =
newHashMap<String, Object>();


map.put("id", 1);


map.put("username","管理员");



//传递Hashmap对象查询用户列表


List<User>list =userMapper.findUserByHashmap(map);


//关闭session


session.close();


}


异常测试:


传递的map中的key和sql中解析的key不一致。


测试结果没有报错,只是通过key获取值为空。


4.1resultType(输出类型)
4.1.0 输出简单类型

参考getnow输出日期类型,看下边的例子输出整型:

Mapper.xml文件


<!--获取用户列表总数 -->



<select id="findUserCount"parameterType="user"resultType="int">



select count(1) fromuser


</select>

Mapper接口


public int findUserCount(User user)throws Exception;

调用:

Public void testFindUserCount()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获取mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);




User user =
new User();


user.setUsername("管理员");



//传递Hashmap对象查询用户列表


int
count =userMapper.findUserCount(user);



//关闭session


session.close();


}

总结:


输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。


使用session的selectOne可查询单条记录。


4.1.1 输出pojo对象

参考findUserById的定义:


Mapper.xml



<!-- 根据id查询用户信息 -->



<selectid="findUserById"parameterType="int"resultType="user">


select * from user where id = #{id}


</select>


Mapper接口:


public UserfindUserById(int id) throws Exception;

测试:

Public void testFindUserById()throws Exception {


//获取session


SqlSession session =
sqlSessionFactory.openSession();



//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//通过mapper接口调用statement


User user = userMapper.findUserById(1);


System.out.println(user);


//关闭session


session.close();


}


使用session调用selectOne查询单条记录。

4.1.2 输出pojo列表

参考selectUserByName的定义:


Mapper.xml


<!--根据名称模糊查询用户信息 -->



<select id="findUserByUsername"parameterType="string"resultType="user">



select * from user whereusername like '%${value}%'


</select>

Mapper接口:

public List<User>findUserByUsername(String
username)throws Exception;

测试:


Public void testFindUserByUsername()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//如果使用占位符号则必须人为在传参数中加%


//List<User>list = userMapper.selectUserByName("%管理员%");


//如果使用${}原始符号则不用人为在参数中加%


List<User>list = userMapper.findUserByUsername("管理员");


//关闭session


session.close();


}


使用session的selectList方法获取pojo列表。

4.1.3 resultType总结:

输出pojo对象和输出pojo列表在sql中定义的resultType是一样的。


返回单个pojo对象要保证sql查询出来的结果集为单条,内部使用session.selectOne方法调用,mapper接口使用pojo对象作为方法返回值。

返回pojo列表表示查询出来的结果集可能为多条,内部使用session.selectList方法,mapper接口使用List<pojo>对象作为方法返回值。


4.1.4 输出hashmap

输出pojo对象可以改用hashmap输出类型,将输出的字段名称作为map的key,value为字段值。

4.2resultMap

resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。


如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系,resultMap实质上还需要将查询结果映射到pojo对象中。


resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。



4.2.0 Mapper.xml定义

使用resultMap指定上边定义的personmap。

4.2.1 定义resultMap

由于上边的mapper.xml中sql查询列和Users.java类属性不一致,需要定义resultMap:userListResultMap将sql查询列和Users.java类属性对应起来


<id />:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个<id />。


Property:表示person类的属性。


Column:表示sql查询出来的字段名。


Column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。

<result />:普通结果,即pojo的属性。


4.2.2 Mapper接口定义

public List<User>findUserListResultMap() throws Exception;

4.3动态sql(重点)

通过mybatis提供的各种标签方法实现动态拼接sql。

4.3.0 If

<!--传递pojo综合查询用户信息 -->



<select id="findUserList"parameterType="user"resultType="user">


select * from user


where 1=1


<if
test="id!=nulland id!=''">


and id=#{id}


</if>


<if
test="username!=nulland username!=''">


and
username like '%${username}%'


</if>



</select>

注意要做不等于空字符串校验。


4.3.1 Where

上边的sql也可以改为:

<selectid="findUserList"parameterType="user"resultType="user">


select * from user


<where>


<if
test="id!=nulland id!=''">


and id=#{id}


</if>


<if
test="username!=nulland username!=''">


and
username like '%${username}%'


</if>


</where>


</select>

<where />可以自动处理第一个and。


4.3.2 foreach

向sql传递数组或List,mybatis使用foreach解析,如下:

4.3.2.0 通过pojo传递list

u需求


传入多个id查询用户信息,用下边两个sql实现:

SELECT * FROM USERS WHERE username LIKE '%张%' AND (id=10 OR id =89 OR id=16)


SELECT * FROM USERS WHERE username LIKE '%张%' id IN (10,89,16)

u在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法

umapper.xml

<iftest="ids!=null and
ids.size>0"
>


<foreachcollection="ids"open="
and id in("
close=")"item="id"separator=",">


#{id}


</foreach>


</if>


u测试代码:

List<Integer> ids=new ArrayList<Integer>();


ids.add(1);//查询id为1的用户


ids.add(10); //查询id为10的用户


queryVo.setIds(ids);


List<User> list = userMapper.findUserList(queryVo);



4.3.2.1 传递单个List

传递List类型在编写mapper.xml没有区别,唯一不同的是只有一个List参数时它的参数名为list。

如下:


uMapper.xml


<selectid="selectUserByList"parameterType="java.util.List"resultType="user">


select * from user


<where>


<!--
传递List,List中是pojo
-->


<if
test="list!=null">


<foreach
collection="list"item="item"open="and
id in("
separator=","close=")">


#{item.id}


</foreach>


</if>


</where>


</select>

uMapper接口

public List<User>selectUserByList(List userlist) throws Exception;

u测试:


Public void testselectUserByList()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//构造查询条件List


List<User> userlist =
newArrayList<User>();


User user =
new User();


user.setId(1);


userlist.add(user);


user =
new User();


user.setId(2);


userlist.add(user);


//传递userlist列表查询用户列表


List<User>list =userMapper.selectUserByList(userlist);


//关闭session


session.close();


}


4.3.2.2 传递单个数组(数组中是pojo):

请阅读文档学习。


uMapper.xml

<!--传递数组综合查询用户信息 -->



<select id="selectUserByArray"parameterType="Object[]"resultType="user">


select * from user


<where>


<!--
传递数组 -->


<if
test="array!=null">


<foreach
collection="array"index="index"item="item"open="and
idin("
separator=","close=")">


#{item.id}


</foreach>


</if>


</where>


</select>


sql只接收一个数组参数,这时sql解析参数的名称mybatis固定为array,如果数组是通过一个pojo传递到sql则参数的名称为pojo中的属性名。


index:为数组的下标。


item:为数组每个元素的名称,名称随意定义


open:循环开始


close:循环结束


separator:中间分隔输出

uMapper接口:

public List<User>selectUserByArray(Object[] userlist) throws Exception;

u测试:

Public void testselectUserByArray()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//构造查询条件List


Object[] userlist =
new Object[2];


User user =
new User();


user.setId(1);


userlist[0]=user;


user =
new User();


user.setId(2);


userlist[1]=user;


//传递user对象查询用户列表


List<User>list =userMapper.selectUserByArray(userlist);


//关闭session


session.close();


}

4.3.2.3 传递单个数组(数组中是字符串类型):

请阅读文档学习。

uMapper.xml

<!--传递数组综合查询用户信息 -->



<select id="selectUserByArray"parameterType="Object[]"resultType="user">


select * from user


<where>


<!--
传递数组 -->


<if
test="array!=null">


<foreach
collection="array"index="index"item="item"open="and
idin("
separator=","close=")">


#{item}


</foreach>


</if>


</where>


</select>


如果数组中是简单类型则写为#{item},不用再通过ognl获取对象属性值了。


uMapper接口:

public List<User>selectUserByArray(Object[] userlist) throws Exception;

u测试:

Public void testselectUserByArray()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//构造查询条件List


Object[] userlist =
new Object[2];


userlist[0]=”1”;


userlist[1]=”2”;


//传递user对象查询用户列表


List<User>list =userMapper.selectUserByArray(userlist);


//关闭session


session.close();


}


4.3.3 Sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下:

<!--传递pojo综合查询用户信息 -->



<select id="findUserList"parameterType="user"resultType="user">


select * from user


<where>


<if
test="id!=nulland id!=''">


and id=#{id}


</if>


<if
test="username!=nulland username!=''">


and
username like '%${username}%'


</if>


</where>


</select>

u将where条件抽取出来:

<sqlid="query_user_where">



<if test="id!=nulland id!=''">


and id=#{id}



</if>



<if test="username!=nulland username!=''">


and
username like '%${username}%'



</if>


</sql>

u使用include引用:

<selectid="findUserList"parameterType="user"resultType="user">


select * from user


<where>


<include
refid="query_user_where"/>


</where>


</select>

注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:


<include
refid="namespace.sql片段”/>

5关联查询5.0商品订单数据模型5.1一对一查询

案例:查询所有订单信息,关联查询下单用户信息。

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

5.1.0 方法:

使用resultType,定义订单信息po类,此po类中包括了订单信息和用户信息:

5.1.0.0 Sql语句:

SELECT


orders.*,


user.username,


userss.address


FROM


orders,


user


WHERE orders.user_id = user.id


5.1.0.1 定义po类

Po类中应该包括上边sql查询出来的所有字段,如下:

publicclass OrdersCustomextends Orders {




private String
username;//用户名称


private Stringaddress;//用户地址


get/set。。。。

OrdersCustom类继承Orders类后OrdersCustom类包括了Orders类的所有字段,只需要定义用户的信息字段即可。

5.1.0.2 Mapper.xml

<!--查询所有订单信息 -->



<select id="findOrdersList"resultType="cn.itcast.mybatis.po.OrdersCustom">



SELECT



orders.*,



user.username,



user.address



FROM



orders, user



WHERE orders.user_id = user.id


</select>

5.1.0.3 Mapper接口:

public List<OrdersCustom>findOrdersList() throws Exception;

5.1.0.4 测试:

Public void testfindOrdersList()throws Exception{


//获取session


SqlSession session =
sqlSessionFactory.openSession();


//获限mapper接口实例


UserMapper userMapper = session.getMapper(UserMapper.class);


//查询订单信息


List<OrdersCustom> list = userMapper.findOrdersList();


System.out.println(list);


//关闭session


session.close();


}

5.1.0.5 总结:

定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。


5.1.1.6 小结:

使用association完成关联查询,将关联查询信息映射到pojo对象中。

5.2一对多查询
5.2.6 小结

使用collection完成关联查询,将关联查询信息映射到集合对象。


5.3多对多查询
5.3.1 小结

一对多是多对多的特例,如下需求:


查询用户购买的商品信息,用户和商品的关系是多对多关系。


需求1:


查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)


企业开发中常见明细列表,用户购买商品明细列表,


使用resultType将上边查询列映射到pojo输出。

需求2:


查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细)


使用resultMap将用户购买的商品明细列表映射到user对象中。

5.4resultMap小结

resultType:


作用:


将查询结果按照sql列名pojo属性名一致性映射到pojo中。


场合:


常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

resultMap:


使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

association:


作用:


将关联查询信息映射到一个pojo对象中。


场合:


为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。


使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。



collection:


作用:


将关联查询信息映射到一个list集合中。


场合:


为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。


如果使用resultType无法将查询结果映射到list集合中。



5.5延迟加载

需要查询关联信息时,使用mybatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,关联信息等用户获取时再加载。


6查询缓存
6.0mybatis缓存介绍

如下图,是mybatis一级缓存和二级缓存的区别图解:

Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。

Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。


6.2二级缓存
6.2.0 原理

下图是多个sqlSession请求UserMapper的二级缓存图解。


二级缓存区域是根据mapper的namespace划分的,相同namespace的mapper查询数据放在同一个区域,如果使用mapper代理方法每个mapper的namespace都不同,此时可以理解为二级缓存区域是根据mapper划分。


每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。


Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象


sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域。

8Mybatis逆向工程

使用官方网站的mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和mapper映射文件。

8.0第一步:mapper生成配置文件:

在generatorConfig.xml中配置mapper生成的详细信息,注意改下几点:

1、 添加要生成的数据库表


2、 po文件所在包路径


3、 mapper文件所在包路径

配置文件如下:


详见generatorSqlmapCustom工程

8.1第二步:使用java类生成mapper文件:

Public void generator()throws Exception{


List<String>warnings =
newArrayList<String>();


boolean overwrite =true;


FileconfigFile =
newFile("generatorConfig.xml");


ConfigurationParsercp =
newConfigurationParser(warnings);


Configurationconfig = cp.parseConfiguration(configFile);


DefaultShellCallbackcallback = new DefaultShellCallback(overwrite);


MyBatisGeneratormyBatisGenerator =
new MyBatisGenerator(config,


callback, warnings);


myBatisGenerator.generate(null);



}



Public static voidmain(String[] args)throws Exception {


try {


GeneratorSqlmapgeneratorSqlmap =
new GeneratorSqlmap();


generatorSqlmap.generator();


}catch(Exception e) {


e.printStackTrace();


}


}

8.2第三步:拷贝生成的mapper文件到工程中指定的目录中
8.2.0 Mapper.xml

Mapper.xml的文件拷贝至mapper目录内


8.2.1 Mapper.java

Mapper.java的文件拷贝至mapper 目录内


注意:mapper xml文件和mapper.java文件在一个目录内且文件名相同。


8.2.2 第四步Mapper接口测试

学会使用mapper自动生成的增、删、改、查方法。

//删除符合条件的记录


int deleteByExample(UserExample example);


//根据主键删除


int deleteByPrimaryKey(String id);


//插入对象所有字段


int insert(User record);


//插入对象不为空的字段


int insertSelective(User record);


//自定义查询条件查询结果集


List<User>selectByExample(UserExample example);


//根据主键查询


UserselectByPrimaryKey(Stringid);


//根据主键将对象中不为空的值更新至数据库


int updateByPrimaryKeySelective(User record);


//根据主键将对象中所有字段的值更新至数据库


int updateByPrimaryKey(User record);


8.3逆向工程注意事项
8.3.0 Mapper文件内容不覆盖而是追加

XXXMapper.xml文件已经存在时,如果进行重新生成则mapper.xml文件内容不被覆盖而是进行内容追加,结果导致mybatis解析失败。


解决方法:删除原来已经生成的mapper xml文件再进行生成。


Mybatis自动生成的po及mapper.java文件不是内容而是直接覆盖没有此问题。


第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台