概述
一、了解内容
-
配置Mybatis两种方式:
-
第一种:Mybatis通过读取mybatis-config.xml文件配置mybatis,通过动态读取配置文件,调用SqlSessionFactoryBuilder的bulid方法获取配置文件字节流获得SqlSessionFactory,创建SqlSession实现类DefultSqlSession的对象,动态代理去执行sql方法
-
第二种:使用Java API配置Mybatis,不去配置任何信息直接把信息写在代码中,然后在按着之前的顺序创建出我们需要的SqlSessionFactory,再进一步得到sqlSession,最后再进行各种数据库操作
例如:使用Java API创建SqlSessionFactory对象,之前是读取配置文件之后再创建,现在是自己把信息写到代码中,然后再创建该对象 public static SqlSessionFactory getSqlSessionFactory() { SqlSessionFactory sqlSessionFactory = null; try { DataSourcedata Source = DataSourceFactory.getDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment); configuration.getTypeAliasRegistry().registerAlias("student",Student.class); configuration.getTypeHandlerRegistry().register(PhoneNumber.class, PhoneTypeHandler.class); configuration.addMapper(StudentMapper.class); sqlSessionFactory = new SqlSessionFactoryBuilder(). build(configuration); } catch (Exception e) { throw new RuntimeException(e); } return sqlSessionFactory; }
- 缺点:将Mapper.xml的sql语句的配置信息写死了,降低了代码的灵活性
-
-
自定义MyBatis日志
-
MyBatis使用其内部LogFactory作为真正的日志类库使用的门面。其内部的LaggerFactory会将日志记录任务委托给如下的所示某一个日志实现,日志记录优先级由上到下顺序递减:
-
SLF4J
-
Apache Commons Logging
-
Log4j2
-
Log4j
-
JDK logging
注意:查看org.apache.ibatis.logging.LogFactory源码可知
-
-
如果MyBatis未发现上述日志记录实现,则MyBatis的日志记录功能无效,如果你的运行环境中,在classpath中有多个可用的日志类库,并且你希望MyBaits使用某个特定的日志实现,你可以在代码中通过调用以下其中一个方法:
org.apache.ibatis.logging.LogFactory.useSlf4jLogging(); org.apache.ibatis.logging.LogFactory.useLog4JLogging(); org.apache.ibatis.logging.LogFactory.useLog4J2Logging(); org.apache.ibatis.logging.LogFactory.useJdkLogging(); org.apache.ibatis.logging.LogFactory.useCommonsLogging(); org.apache.ibatis.logging.LogFactory.useStdOutLogging();
-
注:如果你想自定义MyBatis日志记录,你应该在调用任何其它方法之前调用以上的其中一个方法
二、映射配置文件Mapper.xml
-
Sql语句调用方式有两种:需要配置映射文件StudentMapper.xml和XxxMapper.java映射接口
- 第一种:通过按照sql语句需求根据SqlSession中的对应方法,传入方法的参数(全包名限定+映射xml的 sql标签id,参数),执行sql语句
- 使用字符串形式调用sql语句,即使接口中没有对应方法名,也不影响执行SQL语句
- 第二种:通过动态代理,有SqlSession的DefaultSQLSession实现类通过层层调用,反射newInstance创建出映射接口对象,调用接口对应xml(CURD标签的id和方法名相同)文件中,操作数据库
- 第一种:通过按照sql语句需求根据SqlSession中的对应方法,传入方法的参数(全包名限定+映射xml的 sql标签id,参数),执行sql语句
-
第一种方式:映射接口全包名,调用SQLSession中sql方法
-
映射文件StudentMapper.xml中有id为"findStudentById"的SQL语句,代码如下:
<?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.briup.mappers.StudentMapper"> <select id="findStudentById" parameterType="int" resultType="Student"> select stud_id as studId, name, email, dob from students where stud_id=#{studId} </select> </mapper> 通过字符串,调用映射文件中的SQL语句 字符串形式为: 映射文件的namespace + sql语句的id 例如: SqlSession sqlSession = MyBatisSqlSessionFactory.openSession(); try{ Student student = sqlSession.selectOne("com.briup.mappers.StudentMapper.findStudentById", 1); System.out.println(student); } finally { sqlSession.close(); } 这种方式容易出错 因为需要自己编写字符串,我们需要检查映射文件中namespace, sql语句定义中对参数和返回值的要求,以保证输入的参数类型和结果返回类型是有效的。
-
第二种:MyBatis中还可以通过使用映射接口Mapper,调用映射文件中的sql
-
对应的规范:
-
sql映射文件中的namespace和映射接口的全限定名要保持一致。
-
sql映射文件中的sql语句id值和映射接口中的方法名要保持一致。
-
sql语句配置的parameterType属性和映射接口中对应的方法的参数类型保持一致。
-
sql语句配置的returnType属性和映射接口中对应的方法的返回值类型保持一致。
例如:映射接口StudentMapper.java package com.briup.mappers; public interface StudentMapper{ Student findStudentById(Integer id); } 通过映射接口,调用映射文件中的SQL语句。 select查询语句要注意 代码如下: SqlSession sqlSession = MyBatisSqlSessionFactory.openSession(); try { StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student stu = studentMapper.findStudentById(1); } finally { sqlSession.close(); }
-
-
-
映射语句的类型:MyBatis提供了不同的标签来配置不同类型的sql语句,如SELECT,INSERT,UPDATE,DELETE。
-
INSERT 插入语句:一个INSERT语句可以在< insert>标签元素中进行配置,如下所示:
<insert id="insertStudent" parameterType="Student"> INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,PHONE) VALUES(#{studId},#{name},#{email},#{phone}) </insert> ID属性为insertStudent, 可以在当前xml文件中的名空间 com.briup.mappers.StudentMapper.insertStudent中唯一标识该sql语句。 parameterType 属性是一个完全限定类名或者是一个类型别名alias。 #{stuId},与insertStudent方法中参数类表中的Student对象的属性名对应 可以如下调用这个sql语句: int count = sqlSession.insert("com.briup.mappers.StudentMapper.insertStudent", student); sqlSession.insert() 方法返回执行 INSERT 语句后所影响的行数。 或者使用映射接口Mapper来调用: public interface Student Mapper{ int insertStudent(Student student); } StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); int count = mapper.insertStudent(student); Sqlsession.commit(); 自动生成主键: 在INSERT语句中,可以自动生成主键列 STUD_ID 的值。 使用useGeneratedKeys和keyProperty属性让数据库生成auto_increment列的值,并将生成的值设置到其中一个输入对象属性内,如下所示: <insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studId"> INSERT INTO STUDENTS(NAME, EMAIL, PHONE) VALUES(#{name},#{email},#{phone}) </insert> 这里STUD_ID列值将会被数据库自动生成(如mysql),并且生成的值会被设置到student对象的studId属性上。 注意: 有些数据库,如oracle,并不支持AUTO_INCREMENT列,但是oracle中可以使用序列来生成主键值。 例如:使用序列my_seq来生成SUTD_ID主键值。使用如下代码来生成主键: drop sequence my_seq; create sequence my_seq; <insert id="insertStudent" parameterType="Student"> <selectKey keyProperty="studId" resultType="int" order="BEFORE"> SELECT my_seq.nextval FROM DUAL </selectKey> INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE) VALUES(#{studId},#{name},#{email},#{phone}) </insert> 这里使用了<selectKey>标签来获取主键值,并将值保存到Student对象的studId 属性上。 属性order="before" 表示,MyBatis将取得序列的下一个值作为主键值,并且在执行INSERT语句之前将值设置到studId属性上。
-
UPDATE语句:在< update>标签元素中进行配置,如下所示:
<update id="updateStudent" parameterType="Student"> UPDATE STUDENTS SET NAME=#{name}, EMAIL=#{email}, PHONE=#{phone} WHERE STUD_ID=#{studId} </update> 可以如下调用这个sql语句: int updateCount = sqlSession.update("com.briup.mappers.StudentMapper.updateStudent", student); sqlSession.update()方法返回执行UPDATE语句之后影响的行数。 或者使用映射接口Mapper来调用: public interface StudentMapper{ int updateStudent(Student student); } StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); int updateCount = mapper.updateStudent(student); sqlSession.commit();
-
DELETE语句:DELETE语句可以在标签元素中进行配置,如下所示:
<delete id="deleteStudent" parameterType="int"> DELETE FROM STUDENTS WHERE STUD_ID=#{id} </delete> 可以如下调用这个sql语句: int deleteCount = sqlSession.delete("com.briup.mappers.StudentMapper.deleteStudent", 1); sqlSession.delete()方法返回 delete 语句执行后影响的行数。 或者使用映射接口Mapper来调用: public interface StudentMapper{ int deleteStudent(int studId); } StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); int deleteCount = mapper.deleteStudent(studId); sqlSession.commit();
-
SELECT 查询语句:MyBatis真正强大的功能,在于映射SELECT查询结果到java的各种类型上。
一个简单的select查询配置,如下所示: <select id="findStudentById" parameterType="int" resultType="Student"> SELECT STUD_ID, NAME, EMAIL, PHONE FROM STUDENTS WHERE STUD_ID=#{studId} </select> 第一种:调用sql语句 Student student = sqlSession.selectOne("com.briup.mappers. StudentMapper.findStudentById", 1); 第二种:使用映射接口Mapper来调用: public interface StudentMapper{ Student findStudentById(Integer studId); } StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); Student student = mapper.findStudentById(studId); 注意,这时候Student对象的studId属性值为空,但是其他属性的值都有。 因为数据库表中的字段为stud_id即查询结果字段名也为stud_id,类中属性名为studId,所以property调用对应的setStudId方法时候,studId为null。 这时给stud_id列起一个别名为studId,和类中属性名保持一致即可。如下所示: <select id="findStudentById" parameterType="int" resultType="Student"> SELECT STUD_ID AS studId, NAME,EMAIL, PHONE FROM STUDENTS WHERE STUD_ID=#{studId} </select>
-
MyBatis执行返回多条结果的SELECT语句查询,如下所示:
<select id="findAllStudents" resultType="Student"> SELECT STUD_ID AS studId, NAME,EMAIL, PHONE FROM STUDENTS </select> 第一种:可以如下调用这个sql语句: List<Student> students = sqlSession.selectList("com.briup.mappers.StudentMapper.findAllStudents"); 第二种:或者使用映射接口Mapper来调用: public interface StudentMapper{ List<Student> findAllStudents(); } StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.findAllStudents(); 注意,除了List集合类型,也可以使用其他类型的集合类,如Set,Map等。 yBatis会根据集合的类型,采用适当的集合实现,如下所示: 对于List,Collection,Iterable类型, MyBatis将返回java.util.ArrayList 对于Map类型, MyBatis 将返回java.util.HashMap 对于Set类型, MyBatis 将返回java.util.HashSet 对于SortedSet类型 MyBatis将返回java.util.TreeSet
-
-
结果集映射 :被用来将SELECT语句的结果集映射到java对象的属性中。
-
在xml映射文件中,先定义出结果集映射resultMap,然后SELECT语句上引用这个resultMap。
-
MyBatis的结果集映射resultMap非常强大,可以使用它指定sql查询出的结果集,会被怎么处理并封装成对象,也可以使用它完成复杂查询的映射,例如一对一、一对多关系的SELECT语句。
-
简单ResultMap
-
定义一个resultMap,代码如下:
<resultMap id="StudentResult" type="com.briup.pojo.Student"> <id property="studId" column="stud_id" /> <result property="name" column="name" /> <result property="email" column="email" /> <result property="phone" column="phone" /> </resultMap> <select id="findAllStudents" resultMap="StudentResult"> SELECT * FROM STUDENTS </select> <select id="findStudentById" parameterType="int" resultMap="StudentResult"> SELECT * FROM STUDENTS WHERE STUD_ID=#{studId} </select> resultMap:标签中的属性: id:属性值在当前名空间内是唯一的。 type:属性值是指定类型的全限定名或者是别名。 resultMap标签中的子标签: <result>子标签 用来将一个result列查询结果集映射到对象的一个属性中。 <id>子标签 和<result>标签功能相同,但是<id>用来映射的是表中的主键。 注意1,在<select>标签中,使用的是resultMap属性,而不是resultType属性。 当<select>标签中配置了resutlMap属性,MyBatis会根据resutlMap标签中定义的列名与对象属性名的 【对应关系】 来自动填充对象中的属性值。 注意2,resultType和resultMap二者只能用其一,不能同时使用。 resultType属性指的是结果集将自动封装成什么类型。这时候默认表中列的名字(查询结果的列名)和类中属性名字一致。 resultMap 属性指的是结果集将按照<resultMap>标签中定义的 【对应关系】 来封装数据。
-
select查询的一些其他情况
- 查询结果列名和列名结果,按照k=v形式存储到map集合
<select>中如何将查询【一条】数据填充到HashMap中? <select id="findStudentById" parameterType="int" resultType="map"> SELECT * FROM STUDENTS WHERE STUD_ID=#{studId} </select> 在上述的<select>语句中,将resultType配置成map, 结果集的【列名】将会作为Map中的key值 而【列值】将作为Map的value值。 HashMap<String,Object> studentMap = sqlSession.selectOne("com.briup.mappers.StudentMapper.findStudentById", studId); studentMap.foreach((k,v)->System.out.println(k+" = "+v));
- 查询结果每一条数据结果,按照k=v进行存储到map集合,然后将多行数据存储到List集合中,每一行数据的列名和列名值存储到map集合中,再讲每一行数据封装成的map集合添加到List集合中
<select>中如何将查询【多条】数据填充到HashMap中? <select id="findAllStudents" resultType="map"> SELECT STUD_ID, NAME, EMAIL, PHONE FROM STUDENTS </select> 由于resultType="map",以及结果集为多行,最终返回的数据类型默认是List<Map<String,Object>>,如下所示: List<Map<String, Object>> studentMapList = sqlSession.selectList("com.briup.mappers.StudentMapper.findAllStudents"); for(Map<String, Object> studentMap : studentMapList) { studentMap.foreach((k,v)->System.out.println(k+" = "+v)); System.out.println("----------------"); }
-
该映射文件对应的映射接口中:映射接口中的抽象方法的返回类型可以随便定为常见的集合类型,Mybatis会按照我们方法中声明的集合类型来进行自动封装。
其他实例1: < select id="findAllStudents_student" resultType="Student"> SELECT STUD_ID AS STUDID,NAME,EMAIL,DOB FROM STUDENTS </select> 但是要注意使用SortedSet的时候,Student类需要实现Comparable接口,否则是不能进行排序的 例如: public List<Student> findAllStudents_List(); 或者 public Set<Student> findAllStudents_Set(); 或者 public SortedSet<Student> findAllStudents_SortedSet(); 其他实例2: < select id="findAllName_list" resultType="String"> SELECT NAME FROM STUDENTS </select> 在该映射文件对应的映射接口中: 把查询到所有名字都放到List集合中并返回 public List<String> findAllName_list(); 其他实例3: <select id="findCount_int" resultType="int"> SELECT count(*) FROM STUDENTS </select> 在该映射文件对应的映射接口中: 把查询到的这个值直接返回 public int findCount_int();
-
-
resultMap之间的继承 (了解)
-
(注:这个可以在下面的一对一映射中进行测试,因为这里需要建立一对一关系的表结构)
-
在sql映射文件中,可以让一个其继承另一个,这样,第一个中定义的对应关系,就可以被第二个继承过来,例如:
<!-- 第一个resultMap --> <resultMap type="Student" id="StudentResult"> <id property="stud Id" column="stud_id" /> <result property="name" column="name" /> <result property="email" column="email" /> <result property="phone" column="phone" /> </resultMap> 假设新增了一个新的实体类Address,该类中有多个属性,分别和数据库中ADDRESSES表对应。 在Student类中又新增加了一个属性Address。 <!-- 第二个resultMap,这里面的address.addrId是按照Student对象中的Address类型的属性在调用address对象的setXxx方法,进行查询结果和对象属性映射封装 --> <resultMap type="Student" id="StudentWithAddressResult" extends="StudentResult"> <result property="address.addrId" column="addr_id" /> <result property="address.street" column="street" /> <result property="address.city" column="city" /> <result property="address.state" column="state" /> <result property="address.zip" column="zip" /> <result property="address.country" column="country" /> </resultMap>
-
其中id为StudentWithAddressResult的resultMap拓展了id为StudentResult的resultMap
-
查询结果不包含address地址信息,就只映射Student数据,你可以使用id为StudentResult的resultMap,如下所示:
查询结果映射student对象的属性不包括address属性 <select id="findStudentById" parameterType="int" resultMap="StudentResult"> SELECT * FROM STUDENTS WHERE STUD_ID=#{stud Id} </select>
-
-
-
查询全部,映射Student数据和Address数据,你可以使用id为StudentWithAddressResult的 resultMap:
xml 查询结果包含address数据,将student的成员变量通过查询结果,全部进行初始化 涉及多表查询:要注意查询两张表的字段有冲突的地方需要设置别名,否则进行数据封装到对象会出现数据错乱(student的id可能会封装到address的id中) <select id="selectStudentWithAddress" parameterType="int" resultMap="StudentWithAddressResult"> SELECT STUD_ID, NAME, EMAIL, PHONE, A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY FROM STUDENTS S LEFT OUTER JOIN ADDRESSES A ON S.ADDR_ID=A.ADDR_ID WHERE STUD_ID=#{studId} </select> 注:该sql语句使用了连接查询中的外连接,也可以使用等值连接
最后
以上就是舒心机器猫为你收集整理的Mybatis-XxxMapper.xml配置文件一、了解内容二、映射配置文件Mapper.xml的全部内容,希望文章能够帮你解决Mybatis-XxxMapper.xml配置文件一、了解内容二、映射配置文件Mapper.xml所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复