mybatis基于注解实现增删改查
使用Maven构建一个项目,导入相应的架包
在pom文件中导入以下架包
<!-- 添加项目jdk编译插件 --> <build> <plugins> <!-- 设置编译版本为1.8 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> <!-- 导入需要的包 --> <dependencies> <!-- 测试包 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> <!-- 数据库驱动包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <!-- mybatis包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> </dependencies>
创建数据库和相应的表,下面放上sql语句
create table stu_info ( s_id int primary key auto_increment, s_name varchar(30) not null, s_age int not null, s_sex char(10) not null, s_tel varchar(20) not null, s_origin varchar(50) not null ) -- 班级信息表 create table class_info ( c_id int primary key auto_increment, c_name varchar(20) not null ) -- 关联表 create table stu_class ( sc_id int primary key auto_increment, s_id int not null, c_id int not null ) info(s_name,s_age,s_sex,s_tel,s_origin) values('小李子',18,'男','18970711655','江西赣州' insert into stu_info(s_name,s_age,s_sex,s_tel,s_origin) values('小李子',18,'男','18875711955','江西赣州'),('春春',17,'男','17679077981','江西赣州'),('廖狗蛋',20,'男','17770719761','江西赣州') -- 添加几个班级 insert into class_info(c_name) values('w10'),('w11'),('w12') -- 把创建的学生添加到班级中 insert into stu_class(s_id,c_id) values(47,1),(48,2),(49,3),(50,2) -- 根据id查询学生信息 select s.*,c.c_name from stu_info s inner join stu_class sc on s.s_id = sc.s_id inner join class_info c on sc.c_id = c.c_id delete from stu_info where s_id = #{id} -- 修改学生信息 update stu_info set s_name = '',s_age = , s_sex = '', s_tel = '',s_origin = where s_id = -- 使用别名方式映射实体类查询学生信息 SELECT s_id as sid ,s_name as sname,s_age as sage, s_sex as ssex, s_tel as stel,s_origin as origin from stu_info select * from stu_info where s_name like '小%' select * from stu_info where s_name like '小%' select * from stu_info where s_age BETWEEN 16 and 18 select * from stu_info where s_age BETWEEN 16 and 17 select * from stu_info where s_age = 17 select count(*) from stu_info select * from stu_info where s_age = 17 and s_origin like '江西%' delete from stu_info where s_id in(10,11,12,10,11,12)
创建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> <!-- typeAliases用于给类型指定别名 --> <typeAliases> <!-- 方式一:使用typeAlias设置别名 type属性指定的是类的完整类名,alias属性指定的是别名 --> <!--<typeAlias type="edu.nf.ch01.entity.Users" alias="Users"/>--> <!-- 方式二:直接给整个实体包定义别名,name属性指定实体所在的包名 ,这样会为每一个实体类自动生成一个别名, 而这个别名就是实体类的类名并且首字母小写--> <package name="edu.wang.ch02.entity"/> </typeAliases> <!-- environments用于配置数据源环境,里面可以配置多个。 environment环境。 每个数据源环境都包含在environment子标签中, default属性指定使用默认的数据源环境是哪个, 对应environment标签的id的值--> <environments default="mysql"> <!-- 配置一个mysql的数据源环境,id是自定义的 --> <environment id="mysql"> <!-- 指定事务管理器,这里使用JDBC的本地事务 --> <transactionManager type="JDBC"/> <!-- 配置数据源,type指定使用mybatis自带的数据库连接池 --> <dataSource type="POOLED"> <!-- 配置数据库的连接属性 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- 数据库驱动 --> <property name="url" value="jdbc:mysql://localhost:3306/student?useSSL=true&useUnicode=true&characterEncoding=utf-8"/> <property name="username" value="root"/> <!-- 数据库账号 --> <property name="password" value="root"/> <!-- 数据库密码 --> </dataSource> </environment> </environments> <!-- 将所有的mapper映射配置文件加入到mappers配置中 --> <mappers>
<!--引入映射文件 -->
<!-- 使用注解不是用配置文件使用class配置 -->
<!--<mapper class="edu.wang.ch02.dao.StudentDao"/>-->
<!-- 使用注解不是用配置文件时也可以使用name配置 -->
<!--<package name="edu.wang.ch02.dao"/>-->
<!-- 当需要使用多表查询的时候使用mapper.xml映射属性字段需要映入xml文件,如果不用则使用上面配置即可 -->
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
</configuration>
创建一个MybatisUtil工具类获取SqlSession会话
package edu.wang.studentsystem.commons; 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.InputStream; public class MybatisUtil { //定义一个全局变量方便调用 private static SqlSessionFactory sqlSessionFactory; static { try { //读取mybatis-config.xml配置文件 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); //获取会话工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); } catch (Exception e) { new RuntimeException(e.getMessage()); } } //获取会话 public static SqlSession getSession(){ //获取一个sql会话 return sqlSessionFactory.openSession(); } /** * * @param autoCommit 如果为真则自动提交事务,否者需要手动提交事务 * @return */ public static SqlSession getSession(boolean autoCommit){ return sqlSessionFactory.openSession(autoCommit); } }
编写一个StudentDao接口使用注解的方法
package edu.wang.ch02.dao; import com.sun.org.apache.xalan.internal.xsltc.runtime.InternalRuntimeError; import edu.wang.ch02.entity.Student; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; /** * @Author Waverly * @Date 2018/9/12 */ public interface StudentDao { /** * 保存用户信息 * @param student * @Insert 注解标识要执行insert语句 * 主键策略: * 方式一:使用@Options注解实现主键自增长 * @Options(keyProperty = "s_id" , useGeneratedKeys = true) * keyProperty="指定要自增长的主键字段" useGeneratedKeys="true" 为真为使用自增长 * 方式二:使用@SelectKey注解生成UUID或sequence主键, * keyProperty指定实体的主键字段,resultType指定生成UUID的类型为String, * before指定为true表示在执行SQL之前生成uuid * statement指定查询数据的函数生成uuid * * 例如:@SelectKey(keyProperty = "id", * resultType = String.class, * before = true,statement = "select uuid() from dual") * * keyProperty ="自增长的主键字段" * resultType = "生成什么类型如(String.class)" * before = true 在执行SQL之前插入 * statement = "select uuid() from dual" :生成的参数UUID * 方式三:自己维护主键生成,不需要任何注解 */ //传入一个Student对象映射每个对应的字段 @Insert("insert into stu_info(s_name,s_age,s_sex,s_tel,s_origin) values(#{sname},#{sage},#{ssex},#{stel},#{origin})") //自动增长,使用了方式一 @Options(keyProperty = "s_id" , useGeneratedKeys = true) void saveStudent(Student student); //根据id删除一条数据 @Delete("delete from stu_info where s_id = #{id}") void delStudentById(Integer id); //根据传入的对象自动映射到对应的字段 @Update("update stu_info set s_name = #{sname},s_age = #{sage} , s_sex = #{ssex}, s_tel = #{stel},s_origin =#{origin} where s_id = #{sid}") void updateStudent(Student student); //因为实体类和数据库中的字段名不一致,所以需要用as把数据库中的每个字段变成实体类中的字段名 @Select(" SELECT s_id as sid ,s_name as sname,s_age as sage, s_sex as ssex, s_tel as stel,s_origin as origin from stu_info") //使用@ResultType注解指定返回结果集的类型, //这个注解并不强制要求,mybatis会通过反射获取方法返回值的Class类型 //@ResultType(List.class) List<Student> findAllStudent(); //统计学生的个数 @Select("select count(*) from stu_info") @ResultType(Integer.class) Integer countStudent(); //多表查询查询所在班级 @Select("select s.*,c.c_name from stu_info s inner join stu_class sc on s.s_id = sc.s_id inner join class_info c on sc.c_id = c.c_id") //使用StudentMapper.xml映射字段属性 @ResultMap("edu.wang.ch02.dao.StudentDao.StuMap") List<Student> getStudentList(); }
创建一个实体类进行映射
package edu.wang.ch02.entity; /** * @Author Waverly * @Date 2018/9/12 */ public class Student { private Integer sid; private String sname; private int sage; private String ssex; private String stel; private String origin;
//一对一关系,一个学生对应一个班级 private ClassInfo classInfo; @Override public String toString() { return "Student{" + "sid=" + sid + ", sname='" + sname + '\'' + ", sage='" + sage + '\'' + ", ssex='" + ssex + '\'' + ", stel='" + stel + '\'' + ", origin='" + origin + '\'' + ",classInfo="+classInfo+'\''+ '}'; } public Student() { } public Student(Integer sid, String sname, int sage, String ssex, String stel, String origin) { this.sid = sid; this.sname = sname; this.sage = sage; this.ssex = ssex; this.stel = stel; this.origin = origin; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public int getSage() { return sage; } public void setSage(int sage) { this.sage = sage; } public String getSsex() { return ssex; } public void setSsex(String ssex) { this.ssex = ssex; } public String getStel() { return stel; } public void setStel(String stel) { this.stel = stel; } public String getOrigin() { return origin; } public void setOrigin(String origin) { this.origin = origin; } }
package edu.wang.ch02.entity; /** * @Author Waverly * @Date 2018/9/19 */ public class ClassInfo { private Integer cid; private String cname; @Override public String toString() { return "ClassInfo{" + "cid=" + cid + ", cname='" + cname + '\'' + '}'; } }
编写StudentMapper.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指定Dao接口的完整类名 mybatis会依据这个接口动态创建一个实现类去实现这个接口, 而这个实现类是一个Mapper对象--> <mapper namespace="edu.wang.ch02.dao.StudentDao"> <!-- 基于mybatis的增删查改的sql映射配置 --> <!-- 插入操作,id指定UserDao接口中的方法名, parameterType指定方法参数的类型, 也可以设置为typeAliases中定义的别名。 useGeneratedKeys属性设置为true表示使用主键自增长, keyProperty属性指定实体中需要自增长的字段名称 sql中的values设置参数的时候使用#{}, #{}是一个ognl表达式(对象图导航语言), 这个表达式最终会被mybatis解析成具体的值, 在这里#{}中指定的是实体中的字段名--> <resultMap id="StuMap" type="Student"> <id column="s_id" property="sid"/><!-- 主键id映射 --> <result column="s_name" property="sname"></result> <result column="s_age" property="sage"></result> <result column="s_sex" property="ssex"></result> <result column="s_tel" property="stel"></result> <result column="s_origin" property="origin"></result> <association property="classInfo" resultMap="classMap"/><!-- 一对一 关系 --> </resultMap> <resultMap id="classMap" type="classInfo"> <id column="c_id" property="cid"/><!-- 映射实体类classInfo中的id --> <result column="c_name" property="cname"/><!-- 映射实体类classInfo中的cname --> </resultMap> </mapper>
注解需要跟配置文件中的id对应
最后编写一下测试类测试是否有效
package edu.wang.ch02.test; import edu.wang.ch02.dao.StudentDao; import edu.wang.ch02.dao.impl.StudentDaoImpl; import edu.wang.ch02.entity.Student; import org.junit.Test; import java.util.List; /** * @Author Waverly * @Date 2018/9/18 */ public class StudentDaoImplTest { /** * 测试根据id删除学生信息的方法 */ @Test public void testDelStudentById(){ StudentDao studentDao = new StudentDaoImpl(); studentDao.delStudentById(40); } /** * 测试添加学生信息的方法 */ @Test public void testSaveStudent(){ Student student = new Student(); student.setSname("张三"); student.setSage(18); student.setStel("18888888"); student.setSsex("男"); student.setOrigin("江西"); new StudentDaoImpl().saveStudent(student); } /** * 测试查询所有学生信息的方法 */ @Test public void testFindAllStudent(){ List<Student> list = new StudentDaoImpl().findAllStudent(); for (Student student : list) { System.out.println(student); } } /** * 测试统计学生的方法 */ @Test public void testCountStudent(){ System.out.println(new StudentDaoImpl().countStudent()); } /** * 测试修改学生的方法 */ @Test public void testUpdateStudent(){ Student student = new Student(); student.setSid(47); student.setSname("张三"); student.setSage(18); student.setStel("18888888"); student.setSsex("男"); student.setOrigin("江西"); new StudentDaoImpl().updateStudent(student); } /** * 测试getStudentList */ @Test public void testGetStudentList(){ List<Student> studentList = new StudentDaoImpl().getStudentList(); for (Student student : studentList) { System.out.println(student); } } }
运行结果