在pom.xml中引入相关依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wlw</groupId> <artifactId>mybatis_hello</artifactId> <version>1.0-SNAPSHOT</version> <!-- 导入依赖 --> <dependencies> <!--MyBatis核心依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--MySql驱动依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> </dependencies> </project>创建并配置mybatis-config.xml
<?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> <!-- 核心配置信息 --> <environments default="wlw_mysql_config"> <!-- 数据库相关配置--> <!-- id 是为这个环境配置起一个名字标识,以便于上面引用--> <environment id="wlw_mysql_config"> <!-- 事务控制类型--> <transactionManager type="jdbc"></transactionManager> <!-- 数据库连接参数,连接池--> <dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- & 转义 & --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_wlw?useUnicode=true & characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> </configuration>注意: mapper.xml默认建议存放在resources中,路径不能以/开头
定义所需CURD操作的实体类
package com.wlw.entity; import java.util.Date; public class User { private Integer id; private String username; private String password; private Boolean gender; private Date registTime; public User(){} public User(Integer id, String username, String password, Boolean gender, Date registTime) { this.id = id; this.username = username; this.password = password; this.gender = gender; this.registTime = registTime; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", gender=" + gender + ", registTime=" + registTime + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Boolean getGender() { return gender; } public void setGender(Boolean gender) { this.gender = gender; } public Date getRegistTime() { return registTime; } public void setRegistTime(Date registTime) { this.registTime = registTime; } }根据所需DAO定义接口、以及方法
package com.wlw.dao; import com.wlw.entity.User; public interface UserDAO { User queryUserById(Integer id); }在resources目录中创建Mapper.xml文件 (UserDAOMapper.xml)
这个Mapper.xml文件就代替了之前我们写的接口DAO的实现类,但要在mybatis-config.xml配置文件中注册之后,才能使用
<?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"> <!--namespace = 所须实现的接口的全限定名,指明是哪个接口的mapper文件 --> <mapper namespace="com.wlw.dao.UserDAO"> <!--描述接口中的方法--> <!-- id值为对应的方法名, #{arg0}代表的是方法中的参数 --> <select id="queryUserById" resultType="com.wlw.entity.User"> select id,username,password,gender,regist_time as registTime from t_user where id=#{arg0} </select> </mapper>将Mapper.xml注册到mybatis-config.xml中
<?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> <!-- 核心配置信息 --> <environments default="wlw_mysql_config"> <!-- 数据库相关配置--> <!-- id 是为这个环境配置起一个名字标识,以便于上面引用--> <environment id="wlw_mysql_config"> <!-- 事务控制类型--> <transactionManager type="jdbc"></transactionManager> <!-- 数据库连接参数,连接池--> <dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- & 转义 & --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_wlw?useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!-- 注册mapper文件--> <mappers> <mapper resource="UserDAOMapper.xml"></mapper> </mappers> </configuration>MyBatis的API操作方式
package com.wlw.test; import com.wlw.dao.UserDAO; import com.wlw.entity.User; 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 java.io.IOException; import java.io.InputStream; public class TestMyBatis { public static void main(String[] args) throws IOException { //MyBatis API //1.加载配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); //2.构建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory 创建 SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //4.通过SqlSession 获得 DAO实现类的对象 UserDAO mapper = sqlSession.getMapper(UserDAO.class);//获取UserDAO对应的实现类对象 //5.测试查询方法 User user1 = mapper.queryUserById(1); User user2 = mapper.queryUserById(2); System.out.println(user1); System.out.println(user2); } }iBatis传统操作方式
package com.wlw.test; import com.wlw.dao.UserDAO; import com.wlw.entity.User; 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 java.io.IOException; import java.io.InputStream; public class TestMyBatis { public static void main(String[] args) throws IOException { //MyBatis API //1.加载配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); //2.构建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory 创建 SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); Object o = sqlSession.selectOne("com.wlw.dao.UserDAO.queryUserById", 1); User user = (User) o; System.out.println(user); /* //4.通过SqlSession 获得 DAO实现类的对象 UserDAO mapper = sqlSession.getMapper(UserDAO.class);//获取UserDAO对应的实现类对象 //5.测试查询方法 User user1 = mapper.queryUserById(1); User user2 = mapper.queryUserById(2); System.out.println(user1); System.out.println(user2); */ } }xxxMapper.xml文件放在com.wlw.dao中(为了结构清晰),会出现不会被编译的问题
在pom.xml文件最后追加< build >标签,以便可以将xmI文件复制到classes中,并在程序运行时正确读取。
同时mybatis-config.xml里面的注册mapper的路径要改
<build> <!-- 更改maven编译规则,解决xxxMapper.xml存放在resources以外路径中的读取问题 --> <resources> <resource> <!-- 资源目录 --> <directory>src/main/java</directory> <includes> <include>*.xml</include><!-- 默认(新添加自定义则失效) --> <include>**/*.xml</include><!-- 新添加 */代表1级目录 **/代表多级目录 --> </includes> <filtering>true</filtering> </resource> </resources> </build> <!-- 注册mapper文件--> <mappers> <!--<mapper resource="UserDAOMapper.xml"></mapper>--> <mapper resource="com/wlw/dao/UserDAOMapper.xml"/> </mappers>这样改完运行测试,肯会出现了(Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 2 字节的 UTF-8 序列的字节 2 无效)异常,这应该是因为改动位置之后,在编译时,UserDAOMapper.xml文件中的中文注释导致乱码异常,删除注释就好;或者重启idea,或者将文件重新保存utf-8格式
对于mybatis-configxml的核心配置中,如果存在需要频繁改动的数据内容,可以提取到jdbc.properties中。
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis_wlw?useUnicode=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=123456修改mybatis-config.xml
<?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> <!--添加jdbc.properties配置文件路径(外部配置、动态替换)--> <properties resource="jdbc.properties"/> <!-- 核心配置信息 --> <environments default="wlw_mysql_config"> <!-- 数据库相关配置--> <!-- id 是为这个环境配置起一个名字标识,以便于上面引用--> <environment id="wlw_mysql_config"> <!-- 事务控制类型--> <transactionManager type="jdbc"></transactionManager> <!-- 数据库连接参数,连接池--> <dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory"> <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> <!-- 注册mapper文件--> <mappers> <!--<mapper resource="UserDAOMapper.xml"></mapper>--> <mapper resource="com/wlw/dao/UserDAOMapper.xml"/> </mappers> </configuration>为实体类定义别名,提高书写效率。
<?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> <!--添加properties配置文件路径(外部配置、动态替换)--> <properties resource="jdbc.properties"/> <!--别名--> <typeAliases> <!-- 第一种方式,具体指向每个实体类的别名--> <!--<typeAlias type="com.wlw.entity.User" alias="user"/>--> <!-- 第二种方式,定义实体类所在的package,每个实体类都会自动注册一个别名=类名,不区分大小写--> <package name="com.wlw.entity"/> </typeAliases> <!-- 核心配置信息 --> <environments default="wlw_mysql_config"> <!-- 数据库相关配置--> <!-- id 是为这个环境配置起一个名字标识,以便于上面引用--> <environment id="wlw_mysql_config"> <!-- 事务控制类型--> <transactionManager type="jdbc"></transactionManager> <!-- 数据库连接参数,连接池--> <dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory"> <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> <!-- 注册mapper文件--> <mappers> <!--<mapper resource="UserDAOMapper.xml"></mapper>--> <mapper resource="com/wlw/dao/UserDAOMapper.xml"/> </mappers> </configuration>pom.xml添加log4j依赖
<!-- 日志依赖:Log4J --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>创建并配置log4j.properties
# Global logging configuration log4j.rootLogger=DEBUG, stdout # MyBatis logging configuration... log4j.logger.org.mybatis.example.BlogMapper=TRACE # 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 级别描述ALL LEVEL打开所有日志记录开关;是最低等级的,用于打开所有日志记录。DEBUG输出调试信息;指出细粒度信息事件对调试应用程序是非常有帮助的。INFO输出提示信息;消息在粗粒度级别上突出强调应用程序的运行过程。WARN输出警告信息;表明会出现潜在错误的情形。ERROR输出错误信息;指出虽然发生错误事件,但仍然不影响系统的继续运行。FATAL输出致命错误;指出每个严重的错误事件将会导致应用程序的退出。OFF LEVEL关闭所有日志记录开关;是最高等级的,用于关闭所有日志记录。增删改是要控制事务的,不然表中的数据是不会发生改变的
事务提交:sqlSession.commit();
事务回滚:sqlSession.rollback();
标签: < delete id="" parameterType="">
<!--删除--> <delete id="deleteUser" parameterType="int"> delete from t_user where id = #{id} </delete>标签: < update id="" parameterType="">
<!--修改--> <update id="updateUser" parameterType="User"> update t_user set username=#{username},password=#{password},gender=#{gender},regist_time=#{registTime} where id=#{id} </update>标签: < insert id="" parameterType="">
<!--新增--> <insert id="insertUser" parameterType="User"> insert into t_user values(#{id},#{username},#{password},#{gender},#{registTime}) </insert>当新增数据时,因为id这一列是主键,可以不填,让数据库自动生成,但是在代码中我们希望看到数据库新增的这个主键,这就需要主键回填
标签: < selectKey id="" parameterType="" order=“AFTERIBEFORE”>
MyBatis只能自动维护库表“列名“与"属性名“相同时的一一对应关系,二者不同时,无法自动ORM。
在SQL中使用as为查询字段添加列别名,以匹配属性名。
<!--查询语句中regist_time是数据库表中的列名,registTime是实体类中的属性名 --> <select id="queryUserById" resultType="User"> select id,username,password,gender,regist_time as registTime from t_user where id=#{arg0} </select>通过< resultMap id="" type="" >映射,匹配列名与属性名。
<!-- id=""定义标识,便于引用 type="User"定义对应的实体类--> <resultMap id="user_resultMap" type="User"> <!--定义更加复杂的 映射规则--> <!-- column="数据库中表的列名(如果sql语句中有别名,要写别名)" property="实体类中的属性名" id标签是描述主键列的,其他普通列是用result标签描述--> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <result column="gender" property="gender"></result> <result column="regist_time" property="registTime"></result> </resultMap> <select id="queryUserById" resultMap="user_resultMap"> select id,username,password,gender,regist_time from t_user where id=#{arg0} </select>实体间的关系:关联关系(拥有has、属于belong):
OneToOne:一对一关系(Passenger-- Passport)OneToMany: 一对多关系(Employee – Department)ManyToMany:多对多关系(Student – Subject)SQL语句:
create table t_passengers( id int primary key auto_increment, name varchar(50), sex varchar(1), birthday date )default charset =utf8; create table t_passports( id int primary key auto_increment, nationality varchar(50), expire date, passenger_id int unique, foreign key (passenger_id) references t_passengers(id) )default charset =utf8; insert into t_passengers values(null,'shine_01','f','2018-11-11'); insert into t_passengers values(null,'shine_02','m','2019-12-12'); insert into t_passports values(null,'China','2030-12-12',1); insert into t_passports values(null,'America','2035-12-12',2); select t_passengers.id,t_passengers.name,t_passengers.sex,t_passengers.birthday, t_passports.id as passId,t_passports.nationality,t_passports.expire from t_passengers join t_passports on t_passengers.id = t_passports.passenger_id where t_passengers.id=1PassengerDAO
package com.wlw.dao; import com.wlw.entity.Passenger; import org.apache.ibatis.annotations.Param; public interface PassengerDAO { //通过旅客id,查询旅客信息及其护照信息 //这是一个关联查询(及联查询) Passenger queryPassengerById(@Param("id") Integer id); }PassengerDAOMapper.xml
注意:指定“一方”关系时(对象) , 使用< association property="" javaType="" >
<?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.wlw.dao.PassengerDAO"> <resultMap id="passenger_passsport" type="Passenger"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="sex" property="sex"></result> <result column="birthday" property="birthday"></result> <!--association这个标签定义 一对一 的关联关系 property属性是描述在主表(对应主表的实体类)中对应的从表的属性 javaType描述的是从表对应的实体类--> <association property="passport" javaType="Passport"> <!-- 下面这些是描述从表对应的实体类中的映射--> <id column="passId" property="id"></id> <result column="nationality" property="nationality"></result> <result column="expire" property="expire"></result> </association> </resultMap> <select id="queryPassengerById" resultMap="passenger_passsport"> select t_passengers.id,t_passengers.name,t_passengers.sex,t_passengers.birthday, t_passports.id as passId,t_passports.nationality,t_passports.expire from t_passengers join t_passports on t_passengers.id = t_passports.passenger_id where t_passengers.id=#{id} </select> </mapper> <!--mybatis-config.xml 中的配置--> <!-- 注册mapper文件--> <mappers> <mapper resource="com/wlw/dao/PassengerDAOMapper.xml"/> </mappers>v public class TestMyBatis { public static void main(String[] args) throws IOException { //测试PassengerDAO 中 一对一关系sql PassengerDAO passengerMapper = MyBatisUtil.getMapper(PassengerDAO.class); Passenger passenger = passengerMapper.queryPassengerById(1); System.out.println("----------------------------"); System.out.println(passenger); System.out.println(passenger.getPassport()); } } /* 执行结果: ---------------------------- Passenger{id=1, name='shine_01', sex=false, birthday=Sun Nov 11 00:00:00 CST 2018} Passport{id=1, nationality='China', expire=Thu Dec 12 00:00:00 CST 2030} */在一对一的双向关系中,实现方式就是在双方的xxMapper.xml中都要定义相关映射关系
以下是护照的Mapper文件(PassportDAOMapper.xml)
<?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.wlw.dao.PassportDAO"> <resultMap id="passport_passenger" type="Passport"> <id column="id" property="id"/> <result column="nationality" property="nationality"/> <result column="expire" property="expire"/> <association property="passenger" javaType="Passenger"> <id column="passenger_id" property="id"/> <result column="name" property="name"/> <result column="sex" property="sex"/> <result column="birthday" property="birthday"/> </association> </resultMap> <select id="queryPassportById" resultMap="passport_passenger"> select t_passports.id,t_passports.nationality,t_passports.expire, t_passengers.id as passenger_id,t_passengers.name,t_passengers.sex,t_passengers.birthday from t_passports join t_passengers on t_passengers.id = t_passports.passenger_id where t_passports.id=#{id} </select> </mapper>PassportDAO
package com.wlw.dao; import com.wlw.entity.Passport; import org.apache.ibatis.annotations.Param; public interface PassportDAO { Passport queryPassportById(@Param("id") Integer id); }在One的那一方要用List< T>来定义Many的一方,如下图:
SQL语句
create table t_departments( id int primary key auto_increment, name varchar(50), location varchar(100) )default charset =utf8; create table t_employees( id int primary key auto_increment, name varchar(50), salary double, dept_id int, foreign key (dept_id) references t_departments(id) )default charset =utf8; insert into t_departments values(1,'教学部','北京'),(2,'研发部','上海'); insert into t_employees values(1,'shine01',10000.5,1),(2,'shine02',20000.5,1), (3,'张三',9000.5,2),(4,'李四',8000.5,2);DepartmentDAOMapper.xml
注意:指定“多方"关系时(集合),使用< collectionon property=”“ ofType="" >
<?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.wlw.dao.DepartmentDAO"> <resultMap id="dept_emp" type="Department"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="location" property="location"/> <!-- collection这个标签定义 一对多(Department 对 Employee) 的关联关系 property属性是描述在主表(对应主表的实体类 Department)中对应的从表的属性 ofType属性描述的是集合里的泛型类型,因为多个员工是存放在了一个list集合中--> <collection property="employees" ofType="Employee"> <id column="emp_id" property="id"/> <result column="emp_name" property="name"/> <result column="salary" property="salary"/> </collection> </resultMap> <select id="queryDepartmentById" resultMap="dept_emp"> <!-- 查询部门,及其所有员工信息--> select t_departments.id,t_departments.name,t_departments.location, t_employees.id as emp_id,t_employees.name as emp_name,t_employees.salary from t_departments join t_employees on t_departments.id = t_employees.dept_id where t_departments.id = #{id} </select> </mapper> <!--之后在mybatis-config.xml文件中注册该DepartmentDAOMapper.xml文件,之后测试-->EmployeeDAOMapper.xml
<?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.wlw.dao.EmployeeDAO"> <resultMap id="emp_dept" type="Employee"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="salary" property="salary"/> <!--因为在Employee实体类中Department的属性信息直接就是一个对象,不是用集合来存储 ,所以用association标签, 而在DepartmentDAOMapper.xml中就要用collection标签来关联放在集合中的mployee--> <association property="department" javaType="Department"> <id column="deptId" property="id"/> <result column="deptName" property="name"/> <result column="location" property="location"/> </association> </resultMap> <select id="queryEmployeeById" resultMap="emp_dept"> <!--查询员工信息 并且 查到对应的部门信息--> select t_employees.id,t_employees.name,t_employees.salary, t_departments.id as deptId,t_departments.name as deptName,t_departments.location from t_employees join t_departments on t_employees.dept_id = t_departments.id where t_employees.id = #{id} </select> </mapper> <!--之后在mybatis-config.xml文件中注册该EmployeeDAOMapper.xml文件,之后测试-->SQL语句:
create table t_students( id int primary key auto_increment, name varchar(50), sex varchar(1) )default charset =utf8; create table t_subjects( id int primary key auto_increment, name varchar(50), grade int )default charset =utf8; create table t_stu_sub( student_id int, subject_id int, foreign key (student_id) references t_students(id), foreign key (subject_id) references t_subjects(id), primary key (student_id,subject_id) )default charset =utf8; insert into t_students values (1,'shine','f'),(2,'wlw','m'); insert into t_subjects values (1001,'JavaSE',1),(1002,'JavaWeb',2); insert into t_stu_sub values (1,1001),(1,1002),(2,1001),(2,1002);SubjectDAOMapper.xml
注意:指定“多方"关系时(集合),使用< collection property=”“ ofType="">
<?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.wlw.dao.SubjectDAO"> <resultMap id="sub_stu" type="Subject"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="grade" property="grade"/> <!--因为Subject实体类中 描述Student2时是用list集合来关联的--> <collection property="students" ofType="Student2"> <id column="stuId" property="id"/> <result column="stuName" property="name"/> <result column="sex" property="sex"/> </collection> </resultMap> <select id="querySubjectById" resultMap="sub_stu"> select t_subjects.id,t_subjects.name,t_subjects.grade, t_students.id as stuId,t_students.name as stuName,t_students.sex from t_subjects join t_stu_sub on t_subjects.id = t_stu_sub.subject_id join t_students on t_stu_sub.student_id = t_students.id where t_subjects.id = #{id}; </select> </mapper>Student2DAOMapper.xml
<?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.wlw.dao.Student2DAO"> <resultMap id="stu_sub" type="Student2"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="sex" property="sex"/> <!--因为 Student2实体类中 描述Subject时是用list集合来关联的--> <collection property="subjects" ofType="Subject"> <id column="subId" property="id"/> <result column="subName" property="name"/> <result column="grade" property="grade"/> </collection> </resultMap> <select id="queryStudent2ById" resultMap="stu_sub"> select t_students.id,t_students.name,t_students.sex, t_subjects.id as subId,t_subjects.name subName,t_subjects.grade from t_students join t_stu_sub on t_students.id = t_stu_sub.student_id join t_subjects on t_stu_sub.subject_id = t_subjects.id where t_students.id = #{id} </select> </mapper>mybatis-config.xml
<!-- 注册mapper文件--> <mappers> <mapper resource="com/wlw/dao/SubjectDAOMapper.xml"/> <mapper resource="com/wlw/dao/Student2DAOMapper.xml"/> </mappers>TestMyBatis
public class TestMyBatis { public static void main(String[] args) throws IOException { //查询多对多 一个课程对应的选择这门课程的学生 /*SubjectDAO subjectMapper = MyBatisUtil.getMapper(SubjectDAO.class); Subject subject = subjectMapper.querySubjectById(1001); System.out.println(subject); List<Student2> students = subject.getStudents(); for (Student2 student : students) { System.out.println(student); }*/ //查询一个学生及这个学生选择的课程 Student2DAO student2Mapper = MyBatisUtil.getMapper(Student2DAO.class); Student2 student2 = student2Mapper.queryStudent2ById(1); System.out.println(student2); List<Subject> subjects = student2.getSubjects(); for (Subject subject : subjects) { System.out.println(subject); } } }< trim prefix=“前缀” suffix=“后缀” prefixOverrides=“去除多余的关键字” suffixOverrides="" > 代替< where>、< set>
<?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.wlw.dao.UserDAO"> <sql id="user_field"> select id,username,password,gender,regist_time as registTime from t_user </sql> <!-- select id,username,password,gender,regist_time as registTime from t_user where username = #{username} or gender = #{gender} --> <select id="queryUser2" resultType="User"> <include refid="user_field"></include> <!--<where> <if test="username != null"> username = #{username} </if> <if test="gender != null"> or gender = #{gender} </if> </where>--> <!-- prefix="where" 补充where关键字 prefixOverrides="or|and" where子句中如果以or或and开头,会被覆盖 --> <trim prefix="where" prefixOverrides="or|and"> <if test="username != null"> username = #{username} </if> <if test="gender != null"> or gender = #{gender} </if> </trim> </select> <update id="updateUser" parameterType="User"> update t_user <!--<set> <if test="username != null"> username=#{username}, </if> <if test="password != null"> password=#{password}, </if> <if test="gender != null"> gender=#{gender}, </if> <if test="registTime != null"> regist_time=#{registTime} </if> </set>--> <!-- prefix="set" 补充一个set suffixOverrides="," 自动将set子句的最后的逗号去除 --> <trim prefix="set" suffixOverrides=","> <if test="username != null"> username=#{username}, </if> <if test="password != null"> password=#{password}, </if> <if test="gender != null"> gender=#{gender}, </if> <if test="registTime != null"> regist_time=#{registTime} </if> </trim> where id = #{id} </update> </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.wlw.dao.UserDAO"> <sql id="user_field"> select id,username,password,gender,regist_time as registTime from t_user </sql> <select id="queryUsers" resultType="User"> <include refid="user_field"></include> </select> <!--<select id="queryUserById" resultType="User"> <include refid="user_field"></include> where id = #{id} </select> <select id="queryUserByUsername" resultType="User"> <include refid="user_field"></include> where username = #{username} </select>--> <!-- select id,username,password,gender,regist_time as registTime from t_user where id = #{id} select id,username,password,gender,regist_time as registTime from t_user where username = #{username} --> <select id="queryUser" resultType="User"> <include refid="user_field"></include> where <if test="id != null"> id = #{id} </if> <if test="username != null"> username = #{username} </if> </select> <!-- select id,username,password,gender,regist_time as registTime from t_user where username = #{username} or gender = #{gender} --> <select id="queryUser2" resultType="User"> <include refid="user_field"></include> <!--<where> <if test="username != null"> username = #{username} </if> <if test="gender != null"> or gender = #{gender} </if> </where>--> <trim prefix="where" prefixOverrides="or|and"> <if test="username != null"> username = #{username} </if> <if test="gender != null"> or gender = #{gender} </if> </trim> </select> <delete id="deleteUser" parameterType="int"> delete from t_user where id = #{id} </delete> <update id="updateUser" parameterType="User"> update t_user <!--<set> <if test="username != null"> username=#{username}, </if> <if test="password != null"> password=#{password}, </if> <if test="gender != null"> gender=#{gender}, </if> <if test="registTime != null"> regist_time=#{registTime} </if> </set>--> <trim prefix="set" suffixOverrides=","> <if test="username != null"> username=#{username}, </if> <if test="password != null"> password=#{password}, </if> <if test="gender != null"> gender=#{gender}, </if> <if test="registTime != null"> regist_time=#{registTime} </if> </trim> where id = #{id} </update> <insert id="insertUser" parameterType="User"> <selectKey order="AFTER" resultType="int" keyProperty="id"> select last_insert_id() </selectKey> insert into t_user values (#{id},#{username},#{password},#{gender},#{registTime}); </insert> <delete id="deleteManyUser" parameterType="java.util.List"> <!-- delete from t_user where id in(x,x,x,x) --> delete from t_user where id in <foreach collection="list" open="(" close=")" separator="," item="id9"> #{id9} </foreach> </delete> <insert id="insertManyUser" parameterType="java.util.List"> <!--insert into t_user values (null,x,x,x,x),(null,x,x,x,x),(null,x,x,x,x)--> insert into t_user values <foreach collection="list" item="user9" separator=","> (null,#{user9.username},#{user9.password},#{user9.gender},#{user9.registTime}) </foreach> </insert> </mapper> package com.wlw.test; import com.wlw.dao.UserDAO; import com.wlw.entity.User; import com.wlw.util.MyBatisUtil; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; public class TestMyBatis { @Test public void test1(){ UserDAO userMapper = MyBatisUtil.getMapper(UserDAO.class); /* User user = userMapper.queryUserById(1); System.out.println(user);*/ System.out.println("----------------------"); List<User> users = userMapper.queryUsers(); for (User user1 : users) { System.out.println(user1); } } @Test public void test2(){ UserDAO userMapper = MyBatisUtil.getMapper(UserDAO.class); User user = new User(); //user.setId(3); user.setUsername("wlw_2"); User user1 = userMapper.queryUser(user); System.out.println(user1); } @Test public void test3(){ UserDAO userMapper = MyBatisUtil.getMapper(UserDAO.class); User user = new User(); user.setUsername("wlw"); user.setGender(false); List<User> users = userMapper.queryUser2(user); for (User user1 : users) { System.out.println(user1); } } @Test public void test4(){ UserDAO userMapper = MyBatisUtil.getMapper(UserDAO.class); User user = new User(1,"shine","1234578",true,null); Integer integer = userMapper.updateUser(user); System.out.println(integer); MyBatisUtil.commit(); } @Test public void test5(){ UserDAO userMapper = MyBatisUtil.getMapper(UserDAO.class); List<Integer> ids = Arrays.asList(1, 3, 4); userMapper.deleteManyUser(ids); MyBatisUtil.commit(); } @Test public void test6(){ UserDAO userMapper = MyBatisUtil.getMapper(UserDAO.class); List<User> users = Arrays.asList(new User(null, "shine", "12396", true, new Date()), new User(null, "wlw", "789456", true, new Date())); userMapper.insertManyUser(users); MyBatisUtil.commit(); } }SqlSession级别的缓存,同一个SqlSession的发起多次同构查询,会将数据保存在一级缓存中。
注意:无需任何配置,默认开启一级缓存。
@Test public void test7(){ //查看一级缓存 SqlSession sqlSession = MyBatisUtil.openSession(); UserDAO userMapper = sqlSession.getMapper(UserDAO.class); List<User> users = userMapper.queryUsers(); System.out.println("============================="); List<User> user2 = userMapper.queryUsers(); //上面的输出结果只有一次sql查询 System.out.println("============================="); SqlSession sqlSession2 = MyBatisUtil.getSession(); //另外一个SqlSession UserDAO userMapper2 = sqlSession2.getMapper(UserDAO.class); List<User> users1 = userMapper2.queryUsers(); //这次会再次出现一次查询 }引入Druid依赖
<dependencies> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> </dependencies>MyDruidDataSourceFactory并继承PooledDataSourceFactory,并替换数据源。
package com.wlw.datasource; import com.alibaba.druid.pool.DruidDataSource; import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory; import javax.sql.DataSource; /** * 连接池 工厂 */ public class MyDruidDataSourceFactory extends PooledDataSourceFactory { public MyDruidDataSourceFactory() { this.dataSource = new DruidDataSource();//替换数据源 } }mybatis-config.xml中连接池相关配置。
<environments default="wlw_mysql_config"> <!-- 数据库相关配置--> <!-- id 是为这个环境配置起一个名字标识,以便于上面引用--> <environment id="wlw_mysql_config"> <!-- 事务控制类型--> <transactionManager type="jdbc"></transactionManager> <!-- 数据库连接参数,连接池--> <dataSource type="com.wlw.datasource.MyDruidDataSourceFactory"> <property name="driverClass" value="${jdbc.driver}"/> <!-- & 转义 & --> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments>注意: < property name=“属性名” />属性名必须与com.alibaba.druid.pool.DruidAbstractDataSource中一致。
pom.xml中引入PageHelper依赖。
<dependencies> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency> </dependencies>在MyBatis-config.xml中添加< plugins>。
<?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> <!--configuration 中的子标签的使用是有顺序的,顺序如下: (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?) --> <!--添加properties配置文件路径(外部配置、动态替换)--> <properties resource="jdbc.properties"/> <!-- 注意标签的使用顺序--> <!-- 二级缓存,默认是开启的--> <settings> <setting name="cacheEnabled" value="true"/> </settings> <!--别名--> <typeAliases> <!-- 第一种方式,具体指向每个实体类的别名--> <!--<typeAlias type="com.wlw.entity.User" alias="user"/>--> <!-- 第二种方式,定义实体类所在的package,每个实体类都会自动注册一个别名=类名,不区分大小写--> <package name="com.wlw.entity"/> </typeAliases> <plugins> <!-- com.github.pagehelper为PageHelper类所在包名,这是分页--> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins> <!-- 核心配置信息 --> <environments default="wlw_mysql_config"> <!-- 数据库相关配置--> <!-- id 是为这个环境配置起一个名字标识,以便于上面引用--> <environment id="wlw_mysql_config"> <!-- 事务控制类型--> <transactionManager type="jdbc"></transactionManager> <!-- 数据库连接参数,连接池--> <dataSource type="com.wlw.datasource.MyDruidDataSourceFactory"> <property name="driverClass" value="${jdbc.driver}"/> <!-- & 转义 & --> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!-- 注册mapper文件--> <mappers> <mapper resource="com/wlw/dao/UserDAOMapper.xml"/> </mappers> </configuration>使用PageHelper提供的静态方法设置分页查询条件。
@Test public void testPage(){ UserDAO mapper = MyBatisUtil.getMapper(UserDAO.class); //在查询前,设置分页 查询第一页,每页2条数据 // PageHelper 对其之后的第一个查询,进行分页功能追加 PageHelper.startPage(2, 2); List<User> users = mapper.queryUsers(); for (User user : users) { System.out.println(user); } // 将查询结果 封装到 PageInfo对象中 PageInfo<User> pageInfo = new PageInfo(users); System.out.println("=================================="); }PageInfo对象中包含了分页操作中的所有相关数据。
使用Pagelnfo保存分页查询结果。
@Test public void testPage(){ UserDAO mapper = MyBatisUtil.getMapper(UserDAO.class); //在查询前,设置分页 查询第一页,每页2条数据 // PageHelper 对其之后的第一个查询,进行分页功能追加 PageHelper.startPage(2, 2); List<User> users = mapper.queryUsers(); for (User user : users) { System.out.println(user); } // 将查询结果 封装到 PageInfo对象中 PageInfo<User> pageInfo = new PageInfo(users); System.out.println(pageInfo); System.out.println("=================================="); }只有在PageHelper.startPage()方法之后的第一个查询会有执行分页。
分页插件不支持带有"for update"的查询语句。
分页插件不支持**“嵌套查询”**,由于嵌套结果方式会导致结果集被折叠,所以无法保证分页结果数量正确。
以下内容并非必备知识,了解即可。
通过在接口中直接添加MyBatis注解,完成CRUD。(不使用xxxMapper.xml文件)
注意:接口注解定义完毕后,需将接口全限定名注册到mybatis-config.xml的< mappers >中。
经验:注解模式属于硬编码到.java文件中,失去了使用配置文件外部修改的优势,可结合需求选用。
package com.wlw.dao; import com.wlw.entity.User; import org.apache.ibatis.annotations.*; import java.util.List; public interface UserDAO { @Select(" select id,username,password,gender,regist_time from t_user") List<User> queryUsers(); } <!-- 注册mapper文件--> <mappers> <!--<mapper resource="com/wlw/dao/UserDAOMapper.xml"/>--> <mapper class="com.wlw.dao.UserDAO"/> <!--使用注解的配置 class="接口全限定名"--> </mappers>思路:查询部门信息时,及联查询所属的员工信息。
DepartmentDao接口中定义queryDepartmentById, 并实现Mapper。EmployeeDao接口中定义queryEmployeeByDeptId, 并实现Mapper,当queryDepartmentById被执行时, 通过< collection >调用queryEmployeeByDeptId方法,并传入条件参数。定义queryEmployeeByDeptId,并书写Mapper,实现根据部门ID查询员工信息
package com.wlw.dao; import com.wlw.entity.Employee; import org.apache.ibatis.annotations.Param; import java.util.List; public interface EmployeeDAO { // 查询员工信息 并且 查到对应的部门信息 Employee queryEmployeeById(@Param("id") Integer id); // 查询某个部门下的所有员工 List<Employee> queryEmployeeByDeptId(@Param("deptId") Integer deptId); } <?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.wlw.dao.EmployeeDAO"> <resultMap id="emp_dept" type="Employee"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="salary" property="salary"></result> <!--<association property="department" javaType="Department"> <id column="deptId" property="id"></id> <result column="deptName" property="name"></result> <result column="location" property="location"></result> </association>--> <association property="department" javaType="Department" select="com.wlw.dao.DepartmentDAO.queryDepartmentById" column="dept_id"/> </resultMap> <select id="queryEmployeeById" resultMap="emp_dept"> select id,name,salary,dept_id from t_employees where id=#{id} <!-- select t_employees.id,t_employees.name,t_employees.salary, t_departments.id as deptId,t_departments.name as deptName,t_departments.location from t_employees join t_departments on t_employees.dept_id = t_departments.id where t_employees.id = #{id} --> </select> <select id="queryEmployeeByDeptId" resultType="Employee"> select id,name,salary from t_employees where dept_id=#{deptId} </select> </mapper>定义queryDepartmentById,井书写Mapper,实现根据部门ID查询部门信息,井及联查询该部门员工信息
package com.wlw.dao; import com.wlw.entity.Department; import org.apache.ibatis.annotations.Param; public interface DepartmentDAO { // 查询部门,及其所有员工信息 Department queryDepartmentById(@Param("id") Integer id); } <?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.qf.dao.DepartmentDAO"> <resultMap id="dept_emp" type="Department"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="location" property="location"></result> <!-- emp_id emp_name salary employees --> <!--<collection property="employees" ofType="Employee"> <id column="emp_id" property="id"></id> <result column="emp_name" property="name"></result> <result column="salary" property="salary"></result> </collection>--> <!-- 嵌套查询,select属性是调用EmployeeDAOMapper.xml中的名为queryEmployeeByDeptId的方法 这个方法需要一个where dept_id=#{deptId} 这样的参数,而column="id" 就为它提供了这个参数 并且这个column="id"的值就是我们查询部门(queryDepartmentById)所查询到的id --> <collection property="employees" ofType="Employee" select="com.wlw.dao.EmployeeDAO.queryEmployeeByDeptId" column="id"> </collection> </resultMap> <select id="queryDepartmentById" resultMap="dept_emp"> select id ,name,location from t_departments where id=#{id} <!-- select t_departments.id,t_departments.name,t_departments.location, t_employees.id as emp_id,t_employees.name as emp_name,t_employees.salary from t_departments join t_employees on t_departments.id = t_employees.dept_id where t_departments.id = #{id} --> </select> </mapper> <!-- 注册mapper文件--> <mappers> <mapper resource="com/wlw/dao/DepartmentDAOMapper.xml"/> <mapper resource="com/wlw/dao/EmployeeDAOMapper.xml"/> </mappers>mybatis-config.xml中开启延迟加载
<?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> <!-- 二级缓存,默认是开启的,但如果真的要把查询结果放到二级缓存中需要在相应的xxxMapper文件中配置<cache/> --> <setting name="cacheEnabled" value="true"/> <!-- 当使用嵌套查询时,如果查询中只用到了一方的数据,则不会触发另一方的查询 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 开启延迟加载(默认false) --> </settings> </configuration> package com.wlw.test; import com.wlw.dao.DepartmentDAO; import com.wlw.dao.EmployeeDAO; import com.wlw.entity.Department; import com.wlw.entity.Employee; import com.wlw.entity.User; import com.wlw.util.MyBatisUtil; import org.junit.Test; import java.io.IOException; import java.util.List; public class MyBatisTest2 { @Test public void test1(){ /*DepartmentDAO mapper = MyBatisUtil.getMapper(DepartmentDAO.class); Department department = mapper.queryDepartmentById(1); System.out.println(department); List<Employee> employees = department.getEmployees(); for (Employee employee : employees) { System.out.println(employee); }*/ EmployeeDAO mapper = MyBatisUtil.getMapper(EmployeeDAO.class); Employee employee = mapper.queryEmployeeById(1); System.out.println(employee); //开启了延迟加载 如果不执行这一句,是不会执行queryDepartmentById System.out.println(employee.getDepartment());//开启了延迟加载 如果不执行这一句,是不会执行queryEmployeeByDeptId } }注意:开启延迟加载后,如果不使用及联数据,则不会触发及联查询操作,有利于加快查询速度、节省内存资源。