1、使用MyBatis实现dao层
1.1、使用MyBatis
实现dao
层的几种方式
1、自定义dao
实现类,在实现中调用SqlSession
的相关方法(使用XML
)
2、只定义dao
接口类,SqlSession
的getMapper
方法生成dao
的代理对象(使用XML
)
3、只定义dao
接口类,SqlSession
的getMapper
方法生成dao
的代理对象(使用注解)
目前的注解的功能并没有XML
强大,所以也可以XML
+注解混合使用
1.2、getMapper
+ XML
实现dao
层
1、两个配置要求
mapper
的namespace
必须是dao
接口类的全类名
mapper
中select
、update
、insert
、delete
的id
值必须和dao
的方法名一致
2、如果update
、insert
、delete
方法的返回值是Boolean
类型
代理对象内部是影响记录数大于0就返回true
参考源码org.apache.ibatis.binding.MapperMethod
private Object rowCountResult(int rowCount) {
final Object result;
if (method.returnsVoid()) {
result = null;
} else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
result = rowCount;
} else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
result = (long) rowCount;
} else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
result = rowCount > 0; // 通过返回值类型确定需要返回的类型
} else {
throw new BindingException("Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType());
}
return result;
}
skill.xml
的代码如下
<mapper namespace="com.sj.dao.SkillDao">
<sql id="sqlList">SELECT * FROM skill</sql>
<select id="get" parameterType="int" resultType="skill">
<include refid="sqlList" /> WHERE id = #{id}
</select>
<select id="list" parameterType="int" resultType="skill">
<include refid="sqlList"/>
</select>
<update id="update" parameterType="skill">
UPDATE skill SET name = #{name}, level = #{level} WHERE id = #{id}
</update>
<insert id="save"
useGeneratedKeys="true"
keyProperty="id"
parameterType="skill">
INSERT INTO skill(name, level) VALUES (#{name}, #{level})
</insert>
<delete id="remove" parameterType="int">
DELETE FROM skill WHERE id = #{id}
</delete>
</mapper>
SkillDao
接口实现如下
package com.sj.dao;
import com.sj.bean.Skill;
import java.util.List;
public interface SkillDao {
boolean save(Skill skill);
boolean update(Skill skill);
boolean remove(Integer id);
Skill get(Integer id);
List<Skill> list();
}
Test
代码实现如下(只写了一个实现)
public void get() {
try (SqlSession session = Mybatises.openSession(true)){
// 代理对象
SkillDao dao = session.getMapper(SkillDao.class);
System.out.println(dao.get(1));
}
}
1.3、getMapper
+注解实现dao
层
1、首先要在mybaits-cofig.xml
中配置dao
的位置
方法一:<mapper class="dao的全类名" />
方法二:<package name="dao所在的包" />
2、常用注解
-
@Select
、@Insert
、@Update
、@Delete
、@SelectedKey
-
@SelectedKey
:等价于前面提到的<selectKey></selectKey>
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty="id", before = false, resultType = Integer.class)
-
@Param
:设置参数名,
java
文件如下
public void list2() {
try (SqlSession session = Mybatises.openSession(true)) {
SkillDao dao = session.getMapper(SkillDao.class);
System.out.println(dao.listByStartAndSize(1, 2));
}
}
SkillDao
接口文件
// 通过注解告知参数名称 start 和size
@Select("SELECT * FROM skill LIMIT #{start}, #{size}")
List<Skill> listByStartAndSize(@Param("start") int start, @Param("size") int size);
不加@Param
注解会报如下错误
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'start' not found. Available parameters are [arg1, arg0, param1, param2]
-
@Options
:设置其他属性值,
@Options(useGeneratedKeys = true, keyProperty = "id")
-
@CacheNameSpace
:对应<cache>
开启二级缓存
@CacheNamespace(flushInterval = 600000, size = 512, eviction = LruCache.class)
-
@Results
、@ResultMap
:对应<resultMap>
, -
@Result
:对应<id>
、<result>
-
@One
对应<association>
, -
@Many
对应<collection>
PersonDao
接口实现
public interface PersonDao {
@Select("SELECT * FROM person WHERE id = #{id}")
@Results(id = "get", value = {
@Result(property = "id", column = "id", id = true),
@Result(property = "name", column = "name"),
// @One 相当于association
@Result(
property = "idCard",
column = "id",
one = @One(fetchType = FetchType.LAZY, select = "com.sj.dao.IdCardDao.getByPerson")
),
// @Many相当于collection标签
@Result(property = "bankCards",
column = "id",
many = @Many(fetchType = FetchType.LAZY,select = "com.sj.dao.BankCardDao.listByPerson")),
@Result(property = "jobs",
column = "id",
many = @Many(fetchType = FetchType.LAZY,select = "com.sj.dao.JobDao.listByPerson"))
})
Person get(Integer id);
@Select("SELECT * FROM Person")
// 引用id为get的Results
@ResultMap("get")
List<Person>list();
}
BankCardDao
接口实现
public interface BankCardDao {
@Select("SELECT * FROM bank_card WHERE person_id = #{presonId}")
List<BankCard> listByPerson(Integer personId);
}
IdCardDao
接口实现
public interface IdCardDao {
@Select("SELECT * FROM id_card WHERE person_id = #{personId}")
IdCard getByPerson(Integer personId);
}
JobDao
接口实现
public interface JobDao {
@Select("SELECT j.* FROM job j JOIN person_job pj ON j.id = pj.job_id AND pj.person_id = #{presonId}")
List<Job> listByPerson(Integer personId);
}
mybatis-config.xml
配置如下
<configuration>
<mappers>
<package name="com.sj.dao"/>
</mappers>
</configuration>
PersonTest
代码如下
public void get() {
try (SqlSession session = Mybatises.openSession(true)){
// 代理对象
PersonDao dao = session.getMapper(PersonDao.class);
System.out.println(dao.get(1));
}
}
-
@ConstructorArgs
:对应<constructor>
, -
@Arg
:对应<idArg>
、<arg>
<resultMap id="rmGet" type="Skill">
<constructor>
<arg name="name" javaType="String" column="name"></arg>
<arg javaType="int" column="level"></arg>
</constructor>
</resultMap>
public Skill(@Param("name") String name, Integer level) {
this.name = name;
this.level = level;
}
- 可以使用
<script>
嵌入其他的XML
标签中的内容
@Insert("<script>" +
"INSERT INTO skill(name, level) VALUES" +
" <foreach collection='skills' item='skill' separator=','>" +
" (#{skill.name}, ${skill.level})" +
" </foreach>" +
"</script>"
)
boolean batchSave(@Param("skills") List<Skill> skills);
- @ConstructorProperties:指定构造函数名称
// 指定构造函数名称
@ConstructorProperties({"age", "name"})
public Dog(int age, String name) {
this.age = age;
this.name = name;
}
<bean id="dog" class="com.sj.domain.Dog">
<constructor-arg value="shiji" name="name"/>
<constructor-arg value="10" name="age" />
</bean>
在mybaits-cofig.xml
中配置如下
<configuration>
<mappers>
<mapper class="com.sj.dao.SkillDao"/>
</mappers>
</configuration>
SkillDao
接口实现如下
@CacheNamespace(flushInterval = 600000, size = 512, eviction = LruCache.class)
public interface SkillDao {
@Insert("INSERT INTO skill(name, level) VALUES (#{name}, #{level})")
@Options(useGeneratedKeys = true, keyProperty = "id")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty="id", before = false, resultType = Integer.class)
boolean save(Skill skill);
@Update("UPDATE skill SET name = #{name}, level = #{level} WHERE id = #{id}")
boolean update(Skill skill);
@Delete("DELETE FROM skill WHERE id = #{id}")
boolean remove(Integer id);
@Select("SELECT * FROM skill WHERE id = #{id}")
Skill get(Integer id);
@Select("SELECT * FROM skill")
List<Skill> list();
// 通过注解告知参数名称 start 和size
@Select("SELECT * FROM skill LIMIT #{start}, #{size}")
List<Skill> listByStartAndSize(@Param("start") int start, @Param("size") int size);
}
Test
代码实现如下(只写了一个实现)
public void get() {
try (SqlSession session = Mybatises.openSession(true)){
// 代理对象
SkillDao dao = session.getMapper(SkillDao.class);
System.out.println(dao.get(1));
}
}
网友评论