MyBatis–单表的CURD操作(原始dao方式)
CURD操作,即指对数据库中实体对象的增create、改Update、查Read、删Delete操作
一、自定义Dao接口实现类
搭建环境
Dao接口:
public interface IStudentDao {
//插入
void insertStudent(Student student);
void insertStudentCacheId(Student student);
//删改
void deleteStudentById(int id);
void updateStudent(Student student);
//查询所有
List<Student> selectAllStudents();
Map<String, Object> selectAllStudentsMap();
//查询指定学生
Student selectStudentById(int id);
Student selectStudentByMap(Map<String, Object> map);
//根据姓名查询
List<Student> selectStudentsByName(String name);
}
Dao实现类:
public class StudentDaoImpl implements IStudentDao {
private SqlSession sqlSession;
@Override
public void insertStudent(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("insertStudent",student);
sqlSession.commit();
} finally{
if(sqlSession!=null){
sqlSession.close();
}
}
}
}
测试:
public class MyTest {
private IStudentDao dao;
@Before
public void before(){
dao = new StudentDaoImpl();
}
}
1.单纯插入数据
映射文件:
<insert id="insertStudent" parameterType="com.hcx.beans.Student">
insert into
student(name,age,score)
values(#{name},#{age},#{score})
</insert>
- id:该sql语句的唯一标识,java代码中要使用该标识。
- “#{}”:对指定参数类型属性值的引用。其底层是通过反射机制,调用student类相关属相的get方法来获取值得。因为底层使用的是反射,所以这里使用的是类的属性名,而非表的字段名。
dao实现类:
@Override
public void insertStudent(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("insertStudent",student);
sqlSession.commit();
} finally{
if(sqlSession!=null){
sqlSession.close();
}
}
}
注意:执行完对DB的修改操作,必须要做Sqlsession的提交。否则,修改将无法同步到DB中。因为使用无参的openSession()方法已经将事务自动提交功能给关闭了。
测试类:
@Test
public void test01(){
Student student = new Student("张三",23,99.8);
dao.insertStudent(student);
}
2.插入后用新id初始化被插入对象
mysql中在插入语句后执行如下语句,则会输出新插入记录的id
insert into student(name,age,score) values('王五',25,95.5);
select @@identity;
映射文件中的标签中,有一个子标签用于获取新插入记录的主键值。
1.以下两种写法均可以完成“使用新插入记录的主键值初始化被插入的对象”的功能:
方式一:
<insert id="insertStudentCatchId" parameterType="com.hcx.beans.Student">
insert into student(name,age,score)
values(#{name},#{age},#{score})
<selectKey resultType="int" keyProperty="id" order="AFTER">
select @@identity
</selectKey>
</insert>
方式二:
<insert id="insertStudentCatchId2" parameterType="com.hcx.beans.Student">
insert into student(name,age,score)
values(#{name},#{age},#{score})
<selectKey resultType="int" keyProperty="id" order="AFTER">
select last_insert_id();
</selectKey>
</insert>
- resultType:指出获取的主键的类型
- keyProperty:指出主键在java类中对应的属性名。此处会将获取的主键值直接封装到被插入的student对象中,即dao中insert()方法的第二个参数对象中。
- order:指出id的生成相对于insert语句的执行是在前还是在后。MySql数据库表中的id,均是先执行insert语句,而后生成id,所以需要设置为after;oracle数据库表中的id,则是在insert执行之前先生成,所以需要设置为before。当前的MyBatis版本,不指定order属性,则会根据所用DBMS,自动选择其值。
2.Dao实现类
@Override
public void insertStudentCacheId(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("insesrtStudentCatchId",student);
sqlSession.commit();
}finally{
if(sqlSession != null) {
sqlSession.close();
}
}
}
3.测试类:
//插入后用新id初始化被插入对象
@Test
public void test02(){
Student student = new Student("张三",23,99.8);
System.out.println("插入前student="+student);
dao.insertStudentCatchId(student);
System.out.println("插入后student="+student);
}
3.删除数据
1.映射文件:
<delete id="deleteStudentById">
delete from student where id=#{id}
</delete>
注意:这里的动态参数id所赋值为#{id}。这个#{}表示这就是个占位符,代表delete()方法的第二个参数。#{}中可以放任意值,无需要与delete方法的第二个参数值相同。
2.dao实现类
@Override
public void deleteStudentById(int id) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.insert("deleteStudentById",id);
sqlSession.commit();
}finally{
if(sqlSession != null) {
sqlSession.close();
}
}
}
3.测试类
@Test
public void test03(){
dao.deleteStudentById(3);
}
4.修改数据
1.映射文件:
<update id="updateStudnet">
update student
set name=#{name},age=#{age},score=#{score}
where id=#{id}
</update>
注意,这里的#{}中,必须要填写update()方法所传第二个参数student对象的属性名称,不能随意填写。
2.dao实现类
@Override
public void updateStudent(Student student) {
try {
sqlSession = MyBatisUtils.getSqlSession();
sqlSession.update("updateStudnet",student);
sqlSession.commit();
}finally{
if(sqlSession != null) {
sqlSession.close();
}
}
}
3.测试类
@Test
public void test04(){
Student student = new Student("得的",26,96.6);
student.setId(5);
dao.updateStudent(student);
}
5.查询所有对象-返回list
1.映射文件
<select id="selectAllStudents" resultType="com.hcx.beans.Student">
select * from student
</select>
注意,resultType属性并非指查询结果最后的类型,而是每查出DB中的一条记录,将该记录封装成为的对象的类型。
2.dao实现类
完成dao实现类的selectAllStudent()方法。使用Sqlsession的selectList()方法完成查询操作。该方法会将查询出的每条记录封装为指定类型对象后,再将最后的结果集封装为list返回。
方法原型为:List selectList(String statement)
statement:映射文件中配置的SQL语句的id。
@Override
public List<Student> selectAllStudents() {
List<Student> students = null;
try {
sqlSession = MyBatisUtils.getSqlSession();
students = sqlSession.selectList("selectAllStudents");
//sqlSession.commit();
}finally{
if(sqlSession != null) {
sqlSession.close();
}
}
return students;
}
注意:在写查询时,由于不是对DB中的数据进行修改,所以无需进行Sqlsession的提交。但最终Sqlsession对象还是需要关闭的。
3.测试类
@Test
public void test05(){
List<Student> students = dao.selectAllStudents();
for (Student student : students) {
System.out.println(student);
}
}
6.查询所有对象-返回Map
1.映射文件
<select id="selectAllStudents" resultType="com.hcx.beans.Student">
select * from student
</select>
2.dao实现类
完成dao实现类的selectStudentMap()方法。使用Sqlsession的selectMap()方法完成查询操作。该查询方法会将查询出的每条记录先封装为指定对象,然后再将该对象作为value,将该对象的指定属性所对应的字段名作为key封装为一个map对象。
方法原型:Map
二、属性名与查询字段名不相同
resultType可以将查询结果直接映射为实体Bean对象的条件是,sql查询的字段名与实体Bean的属性名一致。因为在将查询结果转换为指定类型对象时,系统自动将查询结果字段名称作为对象的属性名,通过反射机制完成对象的创建。
当sql查询结果的字段名和实体Bean的属性名不一致时,将无法创建出需要类型的对象。此时有两种解决方案:查询字段使用别名或使用结果映射resultMap
1.修改student表
2.dao接口
public interface IStudentDao {
Student selectStudentById(int id);
}
3.测试类
public class MyTest {
@Test
public void test1(){
IStudentDao dao = new StudentDaoImpl();
Student student = dao.selectStudentById(3);
System.out.println(student);
}
}
4.dao实现类
public class StudentDaoImpl implements IStudentDao {
@Override
public Student selectStudentById(int id) {
SqlSession sqlSession = null;
Student student = null;
try {
sqlSession = MyBatisUtils.getSqlSession();
student = sqlSession.selectOne("selectById2",id);
} finally{
if(sqlSession!=null){
sqlSession.close();
}
}
}
}
解决方式一:查询字段使用别名
虽然属性名称与表中的字段名称不一样,但可以为查询结果的字段名称赋予别名,让别名与实体Bean的属性相同。这样框架也可以根据查询结果利用反射机制将对象创建。
在映射文件mapper中添加如下映射。注意,由于表的score字段名与student类的属性名相同,所以这里无需使用别名。
<select id="selectStudentById" resultType="Student">
select tid id,tname name,tage,age,score
from student where tid=#{tid}
</select>
解决方式二:使用结果映射resultMap
可以使用结果映射resultMap来建立映射关系,完成由字段到属性的映射,达到将查询结果封装为对象的目的。resultMap是对resultType的增强。
<resultMap type="Student" id="studentMapper">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<result column="tage" property="age"/>
</resultMap>
<select id="selectStudentById" resultMap="studentMapper">
select tid, tname, tage, score
from student where tid=#{tid}
</select>
标签中定义了由type指定的类的属性名到表中字段名称的映射关系。根据这个映射关系,框架利用反射机制创建相应对象。
- type:指定要映射的实体类
- id:指定该resultMap映射关系的名称
- id标签:id的字段名column与实体类的属性property间的映射关系
- result标签:id以外其他字段名column与实体类的属性property间的映射关系
如果字段名与实体类的属性名相同的情况,可以不写入中。