MyBatis基础练习
项目目录结构:
依赖包:
<dependencies> <!--单测--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version> </dependency> <!--MyBatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.4</version> </dependency> <!--到slf4j与log4j的关联jar包,通过这个东西,将对slf4j接口的调用转换为对log4j的调用,不同的日志实现框架,这个转换工具不同--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> <scope>test</scope> </dependency> <!--alibaba 数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
实体类:
public class Department { private int departmentId; private String departmentName; public int getDepartmentId() { return departmentId; } public void setDepartmentId(int departmentId) { this.departmentId = departmentId; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } public Department() { } public Department(int departmentId, String departmentName) { this.departmentId = departmentId; this.departmentName = departmentName; } @Override public String toString() { return "Department{" + "departmentId=" + departmentId + ", departmentName='" + departmentName + '\'' + '}'; } }
mybatis-config.xml配置
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--配置的属性都是可外部配置且可动态替换的--> <properties resource="database.properties" /> <settings> <setting name="logImpl" value="SLF4J"/> </settings> <!--定义别名,存在的意义仅在于用来减少类完全限定名的冗余。--> <typeAliases> <!--使用扫描包,扫描指定包下的所有类,扫描之后的别名就是类名(不区分大小写),建议使用的时候和类名一致。--> <package name="cn.pojo"/> </typeAliases> <!--环境数据源--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="cn.util.DruidDataSourceFactory"> <property name="driverClassName" 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 到哪里查找sql映射语句--> <mappers> <mapper resource="mapper/PracticeMapper.xml" /> </mappers> </configuration>
工具类:
MyBatisUtil
public class MyBatisUtil { //创建SqlSessionFactory工厂 public static SqlSessionFactory factory; static { InputStream is = null; try { //读取mybatis-config.xml is = Resources.getResourceAsStream("mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(is); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession createSqlSession(){ return factory.openSession(false);//关闭自动提交事物 } public static void closeSqlSession(SqlSession sqlSession){ if(null!=sqlSession){ sqlSession.close(); } } }
阿里云Druid数据源类
public class DruidDataSourceFactory extends PooledDataSourceFactory { public DruidDataSourceFactory(){ this.dataSource = new DruidDataSource(); } }
database.properties
jdbc.driver:com.mysql.cj.jdbc.Driver jdbc.url:jdbc:mysql://localhost:3306/tests?characterEncoding=utf8&useSSL=false&serverTimezone=UTC jdbc.username:root jdbc.password:123456
log4j.properties
### set log levels ### log4j.rootLogger = DEBUG,Console,File ### Output To Console ### log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.Target=System.out log4j.appender.Console.layout=org.apache.log4j.PatternLayout #log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n #log4j.appender.Console.layout.ConversionPattern= [%p] %d{yyyy-MM-dd HH\:mm\:ss,SSS} %c{1}:%L - %m%n log4j.appender.Console.layout.ConversionPattern= %d{ABSOLUTE} %5p %c{1}:%L - %m%n #log4j.appender.File.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n ### Output To File ### log4j.appender.File=org.apache.log4j.RollingFileAppender log4j.appender.File.File=d:\\mylog.log #log4j.appender.File.DatePattern=_yyyyMMdd'.log' log4j.appender.File.MaxFileSize=10MB #log4j.appender.File.Threshold=ALL log4j.appender.File.layout=org.apache.log4j.PatternLayout log4j.appender.File.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n
dao
public interface PracticeMapper { //查询所有部门 public List<Department> queryDepartmentList(); //根据部门ID,查询单个部门信息 public Department queryDepartmentByDepartmentId(@Param("departmentId")Integer departmentId); /** * 根据部门名称,模糊查询部门信息 * @param departmentName * @return */ public List<Department> queryDepartmentListLikeByDepartmentName(@Param("departmentName")String departmentName); //添加一个部门 public Integer insertDepartmentList(Department department); //删除一个部门,根据部门ID public Integer deleteDepartmentByDepartmentId(@Param("departmentId")Integer departmentId); //修改一个部门,根据部门ID public Integer updateDepartentByDepartmentId(@Param("departmentName")String departmentName,@Param("departmentId")Integer departmentId); //如果输入了部门名称,就按部门名称来查询,否则查询所有部门 public List<Department> queryDepartmentIf(@Param("departmentName")String departmentName); //where和if 如果有部门名称和部门ID,查询单个部门,否则查询所有部门 public List<Department> queryDepartmentIfAndTrim(Department department); //if+set进行更新操作 public Integer updateDepartmentIfAndSet(Department department); //foreach 根据部门ID查询多条信息 public List<Department> queryDepartmentByArrayDepartmentId(Integer[] departmentId); //List类型的foreach迭代 public List<Department> queryDepartmentByListDepartmentId(List<Integer> departmentId); }
PracticeMapper.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="cn.dao.PracticeMapper"> <!--开启mybatis的二级缓存--> <!-- 配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用, 而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。 --> <!-- 二级缓存是事务性的。 这意味着,当 SqlSession 完成并提交时,或是完成并回滚, 但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。 flushCache=true:将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 --> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> <!-- id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致 parameterType:参数的类型,使用动态代理之后和方法的参数类型一致 --> <!--基本查询--> <!--查询所有部门--> <select id="queryDepartmentList" parameterType="Department" resultType="Department"> SELECT <include refid="DepartmentInfo"/> from tests.department </select> <!--根据部门ID,查询单个部门信息--> <select id="queryDepartmentByDepartmentId" parameterType="Department" resultType="Department"> SELECT <include refid="DepartmentInfo"></include> from tests.department where departmentId = #{departmentId} </select> <!--根据部门名称,模糊查询部门信息--> <select id="queryDepartmentListLikeByDepartmentName" parameterType="String" resultType="Department"> SELECT <include refid="DepartmentInfo"></include> FROM tests.department WHERE departmentName LIKE CONCAT('%',#{departmentName},'%') </select> <!--添加一个部门--> <insert id="insertDepartmentList" parameterType="Department"> INSERT INTO department (departmentName) VALUES (#{departmentName}); </insert> <!--删除一个部门--> <delete id="deleteDepartmentByDepartmentId" parameterType="Integer"> delete from department where departmentId = #{departmentId} </delete> <!--修改一个部门,根据部门ID--> <update id="updateDepartentByDepartmentId" parameterType="Department"> update department set departmentName= #{departmentName} where departmentId = #{departmentId} </update> <!--SQL代码片段--> <sql id="DepartmentInfo"> departmentId,departmentName </sql> <!--动态sql查询--> <!--if 如果输入了部门名称,就按部门名称来查询,否则查询所有部门--> <select id="queryDepartmentIf" parameterType="String" resultType="Department"> SELECT <include refid="DepartmentInfo"/> from tests.department WHERE 1=1 <if test="''!=departmentName and null != departmentName"> AND departmentName LIKE CONCAT('%',#{departmentName},'%') </if> </select> <!--if和trim 如果有部门名称和部门ID,查询单个部门,否则查询所有部门--> <!--trim 会自动删除and和or,并且会自动识别标签是否有返回值,有则加上前缀(prefix)和后缀(suffix)--> <select id="queryDepartmentIfAndTrim" parameterType="Department" resultType="Department"> SELECT <include refid="DepartmentInfo"/> from tests.department <trim prefix="where" prefixOverrides="and |or"> <if test="''!=departmentName and null != departmentName"> AND departmentName = #{departmentName} </if> <if test="''!=departmentId and null != departmentId"> AND departmentId = #{departmentId} </if> </trim> </select> <!--if+set 进行更新操作--> <update id="updateDepartmentIfAndSet" parameterType="Department"> update department <set> <if test="''!=departmentName and null != departmentName">departmentName=#{departmentName},</if> <if test="''!=departmentId and null != departmentId">departmentId=#{departmentId}</if> </set> where departmentId = #{departmentId} </update> <!--foreach 根据部门ID查询多条信息--> <!-- item:集合中每个元素进行迭代的别名 open:以什么开始 close:以什么结束 separator:以什么分隔 collection:若入参为单参数,且参数类型是一个List的时候,collection属性值为list 若入参为单参数,且参数类型是一个数组的时候,collection属性值为array 若入参为多参数,就需要将他们封装为一个Map进行处理 --> <select id="queryDepartmentByArrayDepartmentId" parameterType="Department" resultType="Department"> SELECT <include refid="DepartmentInfo"></include> from tests.department where departmentId in <foreach collection="array" item="departmentId" open="(" close=")" separator=","> ${departmentId} </foreach> </select> <!--List类型的foreach迭代--> <select id="queryDepartmentByListDepartmentId" parameterType="Department" resultType="Department"> SELECT <include refid="DepartmentInfo"></include> from tests.department where departmentId in <foreach collection="list" item="departmentId" open="(" close=")" separator=","> ${departmentId} </foreach> </select> </mapper>
单测
public class PracticeMapperTest { private static final Logger logger = LoggerFactory.getLogger(PracticeMapperTest.class); SqlSession sqlSession = MyBatisUtil.createSqlSession(); /** * 查询所有部门 * * @throws IOException */ @Test public void queryDepartmentList() throws IOException { //获取mapper接口的对象 List<Department> departments = sqlSession.getMapper(PracticeMapper.class).queryDepartmentList(); for (Department department : departments) { System.out.println(department.toString()); } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } /** * 根据部门ID,查询单个部门信息 */ @Test public void queryDepartmentByDepartmentId(){ Department department = sqlSession.getMapper(PracticeMapper.class).queryDepartmentByDepartmentId(5); System.out.println(department); MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } /** * 根据部门名称,模糊查询部门信息 */ @Test public void queryDepartmentListLikeByDepartmentName(){ List<Department> list = sqlSession.getMapper(PracticeMapper.class).queryDepartmentListLikeByDepartmentName("气"); for(Department item:list){ System.out.println(item); } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } /** * 添加一个部门 */ @Test public void insertDepartmentList(){ Department department = new Department(); department.setDepartmentName("卡牌部门"); Integer integer = sqlSession.getMapper(PracticeMapper.class).insertDepartmentList(department); if(integer > 0){ sqlSession.commit();//自动提交 }else{ sqlSession.rollback();//回滚 } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } /** * 删除一个部门 */ @Test public void deleteDepartmentByDepartmentId(){ Integer integer = sqlSession.getMapper(PracticeMapper.class).deleteDepartmentByDepartmentId(11); if(integer > 0){ sqlSession.commit();//自动提交 }else{ sqlSession.rollback();//回滚 } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } /** * 修改一个部门,根据部门ID */ @Test public void updateDepartentByDepartmentId(){ Integer integer = sqlSession.getMapper(PracticeMapper.class).updateDepartentByDepartmentId( "灵气部门",4); if(integer > 0){ sqlSession.commit();//自动提交 }else{ sqlSession.rollback();//回滚 } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } /** * 如果输入了部门名称,就按部门名称来查询,否则查询所有部门 */ @Test public void queryDepartmentIf(){ List<Department> list = sqlSession.getMapper(PracticeMapper.class).queryDepartmentIf("魔"); for(Department item : list){ System.out.println(item); } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } //where和if 如果有部门名称和部门ID,查询单个部门,否则查询所有部门 @Test public void queryDepartmentIfAndTrim(){ Department department = new Department(); department.setDepartmentName("灵气部门"); List<Department> list = sqlSession.getMapper(PracticeMapper.class).queryDepartmentIfAndTrim(department); for(Department item : list){ System.out.println(item); } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } //if+set进行更新操作 @Test public void updateDepartmentIfAndSet(){ Department department = new Department(); department.setDepartmentId(4); department.setDepartmentName("仙气大陆"); Integer integer = sqlSession.getMapper(PracticeMapper.class).updateDepartmentIfAndSet(department); if(integer > 0){ sqlSession.commit();//自动提交 }else{ sqlSession.rollback();//回滚 } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } //foreach 根据部门ID查询多条信息 @Test public void queryDepartmentByArrayDepartmentId(){ Integer[] integers = {3,5,8}; List<Department> departments = sqlSession.getMapper(PracticeMapper.class).queryDepartmentByArrayDepartmentId(integers); for(Department items: departments){ System.out.println(items); } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } //List类型的foreach迭代 @Test public void queryDepartmentByListDepartmentId(){ List<Integer> list = new ArrayList<Integer>(); list.add(3); list.add(9); List<Department> departments = sqlSession.getMapper(PracticeMapper.class).queryDepartmentByListDepartmentId(list); for(Department items: departments){ System.out.println(items); } MyBatisUtil.closeSqlSession(sqlSession);//关闭资源 } }
一对一
实体类
public class Department { private int departmentId; private String departmentName; public int getDepartmentId() { return departmentId; } public void setDepartmentId(int departmentId) { this.departmentId = departmentId; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } public Department() { } public Department(int departmentId, String departmentName) { this.departmentId = departmentId; this.departmentName = departmentName; } @Override public String toString() { return "Department{" + "departmentId=" + departmentId + ", departmentName='" + departmentName + '\'' + '}'; } }
public class Employees { private int employeesId; private String employeesName; private int departmentId; private String employeesAddress; private Date employeesBirthday; //java.sql.Date; private Department department; public Employees() { } public Employees(int employeesId, String employeesName, int departmentId, String employeesAddress, Date employeesBirthday, Department department) { this.employeesId = employeesId; this.employeesName = employeesName; this.departmentId = departmentId; this.employeesAddress = employeesAddress; this.employeesBirthday = employeesBirthday; this.department = department; } public int getEmployeesId() { return employeesId; } public void setEmployeesId(int employeesId) { this.employeesId = employeesId; } public String getEmployeesName() { return employeesName; } public void setEmployeesName(String employeesName) { this.employeesName = employeesName; } public int getDepartmentId() { return departmentId; } public void setDepartmentId(int departmentId) { this.departmentId = departmentId; } public String getEmployeesAddress() { return employeesAddress; } public void setEmployeesAddress(String employeesAddress) { this.employeesAddress = employeesAddress; } public Date getEmployeesBirthday() { return employeesBirthday; } public void setEmployeesBirthday(Date employeesBirthday) { this.employeesBirthday = employeesBirthday; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } @Override public String toString() { return "Employees{" + "employeesId=" + employeesId + ", employeesName='" + employeesName + '\'' + ", departmentId=" + departmentId + ", employeesAddress='" + employeesAddress + '\'' + ", employeesBirthday=" + employeesBirthday + ", department=" + department + '}'; } }
Mapper
public Employees getEmployeesListByEmployeesId(@Param("employeesId")Integer employeesId);
Mapper.xml
<resultMap id="employeesDepartmentList" type="Employees"> <id property="employeesId" column="employeesId"/> <result property="employeesName" column="employeesName"/> <result property="employeesAddress" column="employeesAddress"/> <result property="employeesBirthday" column="employeesBirthday"/> <result property="departmentId" column="departmentId"/> <association property="department" javaType="Department"> <id property="departmentId" column="departmentId"/> <result property="departmentName" column="departmentName"/> </association> </resultMap> <!--1对一查询 查询出员工id为2的员工信息和他的部门信息--> <select id="getEmployeesListByEmployeesId" resultMap="employeesDepartmentList" > select e.employeesId,e.employeesName,e.employeesAddress,e.employeesBirthday,e.departmentId,d.departmentName from employees e,department d where e.employeesId = #{employeesId} and e.departmentId = d.departmentId </select>
单侧
//1对一查询 查询出员工id为2的员工信息和他的部门信息 @Test public void getEmployeesListByEmployeesId(){ Integer integer = 3; Employees employees = sqlSession.getMapper(PracticeMapper.class).getEmployeesListByEmployeesId(integer); System.out.println(employees); }
一对多
修改mapper
public List<Employees> getEmployeesListByDepartmentId(@Param("departmentId")Integer departmentId);
修改mapper.xml
<!--1对多查询 根据部门ID查询多此部门下的员工信息--> <select id="getEmployeesListByDepartmentId" resultMap="employeesDepartmentList"> select e.employeesId,e.employeesName,e.employeesAddress,e.employeesBirthday,e.departmentId,d.departmentName from employees e,department d where e.departmentId = #{departmentId} and e.departmentId = d.departmentId </select>
单侧
//1对多查询 根据部门ID查询多此部门下的员工信息 @Test public void getEmployeesListByDepartmentId(){ Integer integer = 2; List<Employees> employees = sqlSession.getMapper(PracticeMapper.class).getEmployeesListByDepartmentId(integer); for(Employees item : employees){ System.out.println(item); }; }