[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlXMVsUR-1602116932300)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200920091057291.png)]
这里借用官网的一句话介绍什么是mybatis:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
首先我们来看一看jdbc连接数据库的连接方法:
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //1、加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); //2、通过驱动管理类获取数据库链接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis", "root", "root"); //3、定义sql语句 ?表示占位符 String sql = "select * from user where username = ?"; //4、获取预处理statement preparedStatement = connection.prepareStatement(sql); //5、设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值 preparedStatement.setString(1, "王五"); //6、向数据库发出sql执行查询,查询出结果集 resultSet = preparedStatement.executeQuery(); //7、遍历查询结果集 while(resultSet.next()){ User user System.out.println(resultSet.getString("id")+" "+resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); }finally{ //8、释放资源 if(resultSet!=null){ try { resultSet.close();//释放结果集 } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(preparedStatement!=null){ try { preparedStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(connection!=null){ try { connection.close();//关闭数据库连接 } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }通过上面的一段jdbc连接数据代码,我们看有哪些不好的地方:
1.在创建connection的时候,存在硬编码问题(也就是直接把连接信息写死,不方便后期维护)
2.preparedStatement对象在执行sql语句的时候存在硬编码问题。
3.每次在进行一次数据库连接后都会关闭数据库连接,频繁的开启/关闭数据连接影响性能。
简单的说一下mybatis相对jdbc的优势:
1.mybatis是把连接数据库的信息都是写在配置文件中,因此不存在硬编码问题,方便后期维护。
2.mybatis执行的sql语句都是通过配置文件进行配置,不需要写在java代码中。
3.mybatis的连接池管理、缓存管理等让连接数据库和查询数据效率更高。
…
这里就通过一张图来对mybatis框架原理进行介绍吧:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hoXpteM1-1602116932304)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200916082215249.png)]
在测试类定义一个获取 getSqlSession的方法:
public SqlSession getSqlSession() { String resource = "mybatis-config.xml"; SqlSession sqlSession = null; // 1 获取mybatis-config.xml的输入流 InputStream is = null; try { is = Resources.getResourceAsStream(resource); // 2 创建SqlSessionFactory对象,完成对配置文件的读取 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); // 3 创建sqlSession sqlSession = factory.openSession(); } catch (Exception e) { e.printStackTrace(); } return sqlSession; }通过sqlSession对象获取对应的Mapper接口
SqlSession sqlSession = getSqlSession(); UserMapper udao = sqlSession.getMapper(UserMapper.class); User user = udao.getUserById(1);//SqlMapConfig.xml是Mybatis的全局配置文件,它的名称可以是任意,但是一般命名都为(SqlMapConfig)
Properties(属性)
Settings(全局参数设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境信息集合)
environment(单个环境信息)
transactionManager(事物)
dataSource(数据源)
mappers(映射器)
properties标签:
Mybatis可以通过该标签来读取java配置信息:
例如在工程中对数据源信息写在db.properties文件中,可以通过properties标签来加载该文件。
db.properties:
db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/mybatis db.username=root db.password=rootSqlMapConfig.xml使用properties标签:
<!-- 通过properties标签,读取java配置文件的内容 --> <properties resource="db.properties" /> <!-- 配置mybatis的环境信息 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事务控制,由mybatis进行管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源,采用dbcp连接池 --> <dataSource type="POOLED"> <property name="driver" value="${db.driver}"/> <property name="url" value="${db.url}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </dataSource> </environment> <!--value="com.mysql.cj.jdbc.Driver" --> <!-- value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&nullCatalogMeansCurrent = true"-->1、 先加载properties中property标签声明的属性
1、 先加载properties中property标签声明的属性
因此在property中的name属性的值和value比properties中的resource属性先加载。后加载的db.properties会覆盖于property加载属性和值。
<property name="db.username",value="root"/>2、 再加载properties标签引入的java配置文件中的属性
3、 parameterType的值会和properties的属性值发生冲突。因此,在properties文件里的内容命名最好加上db.代表是跟数据源相关的属性,这样就不容易跟以后的属性发生冲突。
settings标签:
该标签时mybatis的全局设置,该设置会影响mybatis的运行。
一般我们使用使用该标签来开启二级缓存和懒加载。
以下是几张settings配置项的说明:
typeAliases标签
该标签是对po类进行别名设置,这样,在后面使用po类的时候就可以直接通过别名引用,而不需要通过po类的全限定名来引用。这样可以提高我们的开发效率。
首先介绍下Mybatis的默认提供的别名有:
别名映射的类型_bytebyte_longlong_shortshort_intint_integerint_doubledouble_floatfloat_booleanbooleanstringStringbyteBytelongLongshortShortintIntegerintegerIntegerdoubleDoublefloatFloatbooleanBooleandateDatedecimalBigDecimalbigdecimalBigDecimal自定义单个别名:这种方式只能定义单个类的别名。
下面的代码就是把com.lc.mybatis.po.User类定义为user的别名
<typeAliases> <!-- 设置单个别名 --> <typeAlias type="com.lc.mybatis.po.User" alias="user"/> </typeAliases>自定义之批量定义别名:
下面代码是把com.lc.mybatis.po类下的所有类都声明别名,默认的别名就是类名(类名大小写都可以)
<!-- 设置别名 --> <typeAliases> <!-- 批量设置别名 --> <!-- package:指定包名称来为该包下的po类声明别名,默认的别名就是类名(类名首字母大小写都可以) --> <package name="com.lc.mybatis.po"/> </typeAliases>MyBatis 可以根据不同的数据库厂商执行不同的语句。
1.1在mybatis-config.xml配置:
<environments default="dev_oracle"> <environment id="dev_mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${user}"/> <property name="password" value="${password}"/> </dataSource> </environment> <environment id="dev_oracle"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${orcl.driver}" /> <property name="url" value="${orcl.url}" /> <property name="username" value="${orcl.username}" /> <property name="password" value="${orcl.password}" /> </dataSource> </environment> </environments> <databaseIdProvider type="DB_VENDOR"> <!-- 为不同的数据库厂商起别名 --> <property name="MySQL" value="mysql" /> <property name="Oracle" value="oracle" /> </databaseIdProvider>1.2在EmployeeMapper.xml中配置:
<select id="getEmpById" resultType="com.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} </select> <select id=" getEmpById" resultType="com.mybatis.bean.Employee" databaseId="mysql"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.mybatis.bean.Employee" databaseId="oracle"> select * from employee where id=#{id} </select>1.3在db.properties配置:
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT user=root password=root orcl.driver=oracle.jdbc.OracleDriver orcl.url=jdbc:oracle:thin:@localhost:1521:orcl orcl.username=qq orcl.password=root该标签的作用是加载映射文件
方式一:
该方式是加载相对于类路径下的映射文件:
<mappers> <mapper resource="com/mybatis/dao/EmployeeMapper.xml"/> </mappers>方式二:
该方式使用全限定路径
<mapper url="file:///D:\workspace_spingmvc\mybatis_01\config\sqlmap\User.xml" />方式三:
该方式使用mapper接口的全限定类名
<mapper class="cn.itcast.lc.mapper.UserMapper"/>此方式要求:
Mapper接口Mapper映射文件名称相同且在同一个目录下。
方式四:
该方式是加载指定包下的所有映射文件
<package name="cn.lc.mybatis.mapper"/>此方式要求:
Mapper接口Mapper映射文件名称相同且在同一个目录下。
获取oracle序列封装到javaBean
<!-- 获取非自增主键的值: Oracle不支持自增;Oracle使用序列来模拟自增; 每次插入的数据的主键是从序列中拿到的值;如何获取到这个值; --> <insert id="addEmp" databaseId="oracle"> <!-- keyProperty:查出的主键值封装给javaBean的哪个属性 order="BEFORE":当前sql在插入sql之前运行 AFTER:当前sql在插入sql之后运行 resultType:查出的数据的返回值类型 BEFORE运行顺序: 先运行selectKey查询id的sql;查出id值封装给javaBean的id属性 在运行插入的sql;就可以取出id属性对应的值 AFTER运行顺序: 先运行插入的sql(从序列中取出新值作为id); 再运行selectKey查询id的sql; --> <selectKey keyProperty="id" order="BEFORE" resultType="Integer"> <!-- 编写查询主键的sql语句 --> <!-- BEFORE--> select EMPLOYEES_SEQ.nextval from dual <!-- AFTER: select EMPLOYEES_SEQ.currval from dual --> </selectKey> <!-- 插入时的主键是从序列中拿到的 --> <!-- BEFORE:--> insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->}) <!-- AFTER: insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(employees_seq.nextval,#{lastName},#{email}) --> </insert>·单个参数 -可以接受基本类型,对象类型,集合类型的值。这种情况MyBatis可直接使用这个参数﹐不需要经过任何处理。 ⭐️·多个参数 -任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1 , param2 ,O,1…,值就是参数的值。 ·命名参数―——为参数使用@Param起一个名字,MyBatis就会将这些参数封 装进map中,key就是我们自己指定的名字
接口使用@Param来传递多个参数:
public Employee getEmpByIdAndLastName(@Param("id")Integer id,@Param("lastName")String lastName);xml配置:
<!-- public Employee getEmpByIdAndLastName(Integer id,String lastName);--> <select id="getEmpByIdAndLastName" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} and last_name=#{lastName} </select>在test测试类封装map
Map<String,Object> map=new HashMap<String,Object>(); map.put("id", 2); map.put("lastname", "zhangsan"); Employee employee=mapper.getEmployeeByMap(map);mapper接口:
//map集合类型 public Employee getEmployeeByMap(Map<String,Object> map);mapper.xml“:
<select id="getEmployeeByMap" resultType="com.mybatis.bean.Employee" databaseId="mysql"> select * from tbl_employee where id=#{id} and lastname=#{lastname} </select>(多个员工对应一个角色),在user表放一个角色表的对象
public class User { private Integer id; // id private String user_Code; // 用户编码 private String user_Name; // 用户名称 private String user_Password; // 用户密码 private Integer gender; // 性别 private Date birthday; // 出生日期 private String phone; // 电话 private String address; // 地址 private Integer userRole; // 用户角色 private String rolename; private Integer created_By; // 创建者 private Date creation_Date; // 创建时间 private Integer modify_By; // 更新者 private Date modify_Date; // 更新时间 private Role role;// 角色对象在UserMapper.xml文件中配置多对一的映射关系:
标签用:
<resultMap id="userlist2" type="cn.pojo.User"> <id property="id" column="id"></id> <result property="user_Code" column="userCode" /> <result property="user_Name" column="userName" /> <result property="user_Password" column="userPassword" /> <result property="gender" column="gender" /> <result property="birthday" column="birthday" /> <result property="phone" column="phone" /> <result property="address" column="address" /> <result property="created_By" column="createdBy" /> <result property="creation_Date" column="creationDate" /> <result property="modify_By" column="modifyBy" /> <result property="modify_Date" column="modifyDate" /> <association property="role" javaType="cn.pojo.Role" resultMap="rolelist"> </association> </resultMap> <resultMap id="rolelist" type="cn.pojo.Role"> <id property="id" column="id" /> <result property="roleCode" column="roleCode" /> <result property="roleName" column="roleName" /> </resultMap>(一个角色对应多名员工)在role表中放一个user的集合:
public class Role { private int id; private String roleCode; private String roleName; private List<User> userlist;在RoleMapper.xml文件中配置一对多的映射关系:
标签用:
<resultMap id="rolelist2" type="cn.pojo.Role"> <id property="id" column="id" /> <result property="roleCode" column="roleCode" /> <result property="roleName" column="roleName" /> <collection property="userlist" ofType="cn.pojo.User" resultMap="userlist"> </collection> </resultMap> <resultMap id="userlist" type="cn.pojo.User"> <id property="id" column="id" /> <result property="user_Code" column="userCode" /> <result property="user_Name" column="userName" /> <result property="user_Password" column="userPassword" /> <result property="gender" column="gender" /> <result property="birthday" column="birthday" /> <result property="phone" column="phone" /> <result property="address" column="address" /> <result property="userRole" column="userRole" /> <result property="created_By" column="createdBy" /> <result property="creation_Date" column="creationDate" /> <result property="modify_By" column="modifyBy" /> <result property="modify_Date" column="modifyDate" /> </resultMap> ```