转载

MyBatis--注解式开发

MyBatis的注解,主要是用于替换映射文件。而映射文件中无非存放着增删改查的sql映射标签。所以,MyBatis注解,就是替换映射文件中的sql标签。

常用注解说明:

注解 说明
@Insert 实现新增
@Update 实现更新
@Delete 实现删除
@Select 实现查询
@Result 实现结果集封装
@Results 可以与@Result 一起使用,封装多个结果集
@ResultMap 实现引用@Results 定义的封装
@One 实现一对一结果集封装
@Many 实现一对多结果集封装
@SelectProvider 实现动态 SQL 映射
@CacheNamespace 实现注解二级缓存的使用

一、基本的CRUD

1.@Insert

其value属性用于指定要执行的insert语句。

2.@SelectKey

用于替换xml中的 <selectKey/> 标签,用于返回新插入数据的id值。

@SelectKey(statement="select @@identity",resultType=int.class,keyProperty="id",before=false
复制代码
  • statement:获取新插入记录主键值得sql语句
  • keyProperty:获取的该主键值返回后初始化对象的那个属性
  • resultType:返回值类型
  • before:指定主键的生成相对于insert语句的执行先后顺序,该属性不能省略

3.@Delete

其value属性用于指定要执行的delete语句。

4.@Update

其value属性用于指定要执行的update语句。

5.@Select

其value属性用于指定要执行的select语句。

程序举例:

SqlMapConfig.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>
    <!-- 引入外部配置文件-->
    <properties resource="jdbcConfig.properties"></properties>
    <!--配置别名-->
    <typeAliases>
        <package name="com.hcx.domain"></package>
    </typeAliases>
    <!-- 配置环境-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定带有注解的dao接口所在位置 -->
    <mappers>
        <mapper class="com.hcx.dao.StudentDao"></mapper>
    </mappers>
</configuration>
复制代码

1.修改dao接口:

public interface IStudentDao {
	@Insert(value={"insert into student(name,age,score) values(#{name},#{age},#{score})"})
	void insertStudent(Student student);	
	
	@Insert("insert into student(name,age,score) values(#{name},#{age},#{score})")
	@SelectKey(statement="select @@identity",resultType=int.class,keyProperty="id",before=false)
	void insertStudentCacheId(Student student);
	
	@Delete(value="delete from student where id=#{id}")
	void deleteStudentById(int id);
	
	@Update("update student set name=#{name},age=#{age},score=#{score} where id=#{id}")
	void updateStudent(Student student);
	
	@Select("select * from student")
	List<Student> selectAllStudents();
	
	@Select("select * from student where id=#{id}")
	Student selectStudentById(int id);
	
	@Select("select * from student where name like '%' #{name} '%'")
	List<Student> selectStudentsByName(String name);
	
}
复制代码

2.删除映射文件

3.修改主配置文件

由于没有了映射文件,所以主配置文件中不能使用 <mapper/> 注册mapper的位置了。需要使用 <package/> 标签

<!-- 注册映射文件 -->
<mappers>  
    <package name="com.hcx.dao"/>  
</mappers>
复制代码

注意:使用了注解之后,不管主配置文件(SqlMapConfig.xml)有没有引用映射文件,都不能存在映射文件。可以删除或者放在其他目录下。

二、实现复杂关系映射

1.@Result当实体属性和数据库字段名称不一致时,使用 @Result 注解声明映射关系

@Results(id = "studentMap",value={
            @Result(id=true,column = "id",property = "studentId"),
            @Result(column = "name",property = "studentName"),
            @Result(column = "age",property = "studentAge"),
            @Result(column = "score",property = "studentScore"),
    })
复制代码

id :唯一标识这段映射,之后可以直接引用,无需重复编写 id=true :标识为主键字段 column :数据库字段名 property :实体属性名

2.@ResultMap引用定义好的ResultMap

Student:

@Data
@ToString
public class Student implements Serializable{
    private Integer studentId;
    private String studentName;
    private int studentAge;
    private double studentScore;
}
复制代码

StudentDao:

public interface StudentDao {

    @Select("select * from student")
    @Results(id = "studentMap",value={
            @Result(id=true,column = "id",property = "studentId"),
            @Result(column = "name",property = "studentName"),
            @Result(column = "age",property = "studentAge"),
            @Result(column = "score",property = "studentScore"),
    })
    List<Student> findAll();

    @Select("select * from student where id=#{id}")
    @ResultMap(value = {"studentMap"})
    Student findById(Integer id);


    @Select("select * from student where name like #{name}")
    @ResultMap(value = {"studentMap"})
    List<Student> findStudentByName(String name);

}
复制代码

AnnotationCrudTest:

public class AnnotationCrudTest {

    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private StudentDao studentDao;

    @Before
    public  void init()throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        studentDao = session.getMapper(StudentDao.class);
    }

    @After
    public  void destroy()throws  Exception{
        session.commit();
        session.close();
        in.close();
    }

    @Test
    public void testFindAll(){
        List<Student> students = studentDao.findAll();
        for(Student student : students){
            System.out.println(student);
        }
    }


    @Test
    public void testFindById(){
        Student student = studentDao.findById(1);
        System.out.println(student);
    }


    @Test
    public  void testFindByName(){
        List<Student> students = studentDao.findStudentByName("%小红%");
        for(Student student : students){
            System.out.println(student);
        }
    }
}
复制代码

三、实现多表复杂查询

1.一对一

Account:

@Data
@ToString
public class Account {
    private Integer id;
    private Integer studentId;
    private Double money;

    //多对一:一个账户只能属于一个学生
    private Student student;
}
复制代码

AccountDao:

public interface AccountDao {
    /**
     * 查询所有账户并获取每个账户所属用户信息
     * @return
     */
    @Select("select * from account")
    @Results(id = "accountMap",value = {
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "studentId",property = "studentId"),
            @Result(column = "money",property = "money"),
            @Result(property = "student",column = "studentId",one = @One(select = "com.hcx.dao.StudentDao.findById",
                    fetchType = FetchType.EAGER))
    })
    List<Account> findAll();
}
复制代码

StudentDao:

public interface StudentDao {

    @Select("select * from student")
    @Results(id = "studentMap",value={
            @Result(id=true,column = "id",property = "studentId"),
            @Result(column = "name",property = "studentName"),
            @Result(column = "age",property = "studentAge"),
            @Result(column = "score",property = "studentScore"),
    })
    List<Student> findAll();

    @Select("select * from student where id=#{id}")
    @ResultMap(value = {"studentMap"})
    Student findById(Integer id);


    @Select("select * from student where name like #{name}")
    @ResultMap(value = {"studentMap"})
    List<Student> findStudentByName(String name);
}
复制代码

AccountTest:

@Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for(Account account : accounts){
            System.out.println(account);
//            System.out.println(account.getStudent());
        }
    }
复制代码

注意:通常对一选择立即加载,对多选择延迟加载

2.一对多

Student:

@Data
@ToString
public class Student implements Serializable{
    private Integer studentId;
    private String studentName;
    private int studentAge;
    private double studentScore;
    //一对多,一个用户对应多个账户
    private List<Account> accounts;
}
复制代码

StudentDao:

public interface StudentDao {

    @Select("select * from student")
    @Results(id = "studentMap",value={
            @Result(id=true,column = "id",property = "studentId"),
            @Result(column = "name",property = "studentName"),
            @Result(column = "age",property = "studentAge"),
            @Result(column = "score",property = "studentScore"),
            @Result(property = "accounts",column = "id",
                    many = @Many(select = "com.hcx.dao.AccountDao.findAccountByStudentId",fetchType = FetchType.LAZY))
    })
    List<Student> findAll();

    @Select("select * from student where id=#{id}")
    @ResultMap(value = {"studentMap"})
    Student findById(Integer id);

    @Select("select * from student where name like #{name}")
    @ResultMap(value = {"studentMap"})
    List<Student> findStudentByName(String name);

}
复制代码

AccountDao:

public interface AccountDao {

    /**
     * 查询所有账户并获取每个账户所属用户信息
     * @return
     */
    @Select("select * from account")
    @Results(id = "accountMap",value = {
            @Result(id = true,column = "id",property = "id"),
            @Result(column = "studentId",property = "studentId"),
            @Result(column = "money",property = "money"),
            @Result(property = "student",column = "studentId",one = @One(select = "com.hcx.dao.StudentDao.findById",
                    fetchType = FetchType.EAGER))
    })
    List<Account> findAll();

    /**
     * 根据学生id查询学生信息
     * @param studentId
     * @return
     */
    @Select("select * from account where studentId=#{studentId}")
    List<Account> findAccountByStudentId(Integer studentId);
}
复制代码

Test:

@Test
    public void testFindAll(){
        List<Student> students = studentDao.findAll();
        for(Student student : students){
            System.out.println(student);
        }
    }

复制代码

四、实现二级缓存

一级缓存:默认就开启:

@Test
    public void testFindById(){
        Student student = studentDao.findById(1);
        System.out.println(student);

        Student student1 = studentDao.findById(1);
        System.out.println(student1);

        //true
        System.out.println(student==student1);
    }
复制代码

在主配置文件中开启二级缓存(默认开启,不配置也可以) sqlMapConfig.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>
    <!-- 引入外部配置文件-->
    <properties resource="jdbcConfig.properties"></properties>
    <!--设置开启二级缓存-->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!--配置别名-->
    <typeAliases>
        <package name="com.hcx.domain"></package>
    </typeAliases>
    <!-- 配置环境-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定带有注解的dao接口所在位置 -->
    <mappers>
        <!--<mapper class="com.hcx.dao.StudentDao"></mapper>-->
        <package name="com.hcx.dao"></package>
    </mappers>
</configuration>
复制代码

在mapper中使用注解 @CacheNamespace(blocking=true)

@CacheNamespace(blocking = true)
public interface StudentDao {

    @Select("select * from student")
    @Results(id = "studentMap",value={
            @Result(id=true,column = "id",property = "studentId"),
            @Result(column = "name",property = "studentName"),
            @Result(column = "age",property = "studentAge"),
            @Result(column = "score",property = "studentScore"),
            @Result(property = "accounts",column = "id",
                    many = @Many(select = "com.hcx.dao.AccountDao.findAccountByStudentId",fetchType = FetchType.LAZY))
    })
    List<Student> findAll();

    @Select("select * from student where id=#{id}")
    @ResultMap(value = {"studentMap"})
    Student findById(Integer id);


    @Select("select * from student where name like #{name}")
    @ResultMap(value = {"studentMap"})
    List<Student> findStudentByName(String name);

}
复制代码

Test:

@Test
    public void testFindOne(){
        SqlSession sqlSession = factory.openSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Student student = studentDao.findById(1);
        System.out.println(student);
        sqlSession.close();

        SqlSession sqlSession1 = factory.openSession();
        StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);

        Student student1 = studentDao1.findById(1);
        System.out.println(student1);

        sqlSession1.close();
        //false
        System.out.println(student==student1);
    }
复制代码
原文  https://juejin.im/post/5dee427af265da33d7441e3d
正文到此结束
Loading...