您的位置:首页 > 其它

通过Mybatis实现对单表的增删改查-通过定义一个接口实现

2017-07-23 22:45 519 查看

Pom.xml文件 定义工程项目依赖的软件库

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>org.vincent</groupId>
<artifactId>mybatisweb</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mybatisweb Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>

</dependencies>
<build>
<!-- 将mybatisweb项目打包成mybatisweb.war自动部署到tomcat服务器的webapps目录下面 -->
<finalName>mybatisweb</finalName>
<plugins>
<plugin>
<!-- 使用 cargo自动化部署 -->
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.4.12</version> <!-- 不能用1.3.2 不然用maven编译不成功 -->
<configuration>
<container>
<!-- 指明使用的tomcat服务器版本 -->
<containerId>tomcat8x</containerId>
<!--指明tomcat服务器的安装目录 -->
<home>C:\fastDev\Tomcat\apache-tomcat-8.5.14</home>
</container>
<configuration>
<type>existing</type>
<!--指明tomcat服务器的安装目录 -->
<home>C:\fastDev\Tomcat\apache-tomcat-8.5.14</home>
<properties><cargo.servlet.port>9090</cargo.servlet.port></properties>
</configuration>
</configuration>
<executions>
<execution>
<id>cargo-run</id>
<phase>install</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>


src/main/resources目录下放置了mybatis的所有配置文件该目录下文件可以直接被java代码引用

为了管理,在src/main/resources目录下新建mybatis目录管理所有mybatis相关的配置信息。

mybatis配置数据源信息

MybatisConfig.xml 在src/main/resources/mybatis目录

<?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>
<!-- 给类设置别名, 在mapper文件中可以使用这个别名,就不用使用那么长的类名了。 -->
<typeAliases>
<typeAlias type="org.vincent.model.Student"
alias="Student"/>
</typeAliases>
<environments default="development">
<environment id="development">
<!--  事务管理 -->
<transactionManager type="JDBC" />
<!-- 配置数据库连接信息 ,没有用数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/javaee" />
<property name="username" value="root" />
<property name="password" value="1557862201" />
</dataSource>
</environment>

</environments>
<mappers>
<!-- 注册SQL映射信息文件,Mapper.xml文件,   Mapper.xml位于src/main/resources/mybatis这个包下,因为src/main/resources/为classpath,所以resource写成mybatis/mappers/Student.xml-->
<mapper resource="mybatis/mappers/Student.xml"/>
</mappers>
</configuration>


设置项目中POJO类和数据库表的映射关系

Student.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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的
例如namespace="org.vincent.mapping.Mapper"就是org.vincent.mapping(包名)+Mapper(Mapper.xml文件去除后缀);
但是如有需要通过定义一个接口方法定义访问数据库接口方法,那么namespace必须取接口全类名。
-->
<mapper namespace="org.vincent.model.IStudentOperation">
<!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为getStudent,id属性值必须是唯一的,不能够重复;
使用parameterType属性指明查询时传递进来使用的参数类型,resultType属性指明查询返回的结果集类型
resultType="org.vincent.domain.Student"就表示将查询结果映射成一个Student类的对象返回
Student类就是student表所对应的实体类
-->
<!--
根据id查询得到一个student对象
org.vincent.model.IStudentOperation.getStudentbyId
id 设置成接口的对应方法名public Student getStudentbyId(int id);
MyBatis会根据结果自动创建一个ResultMap对象,然后基于查找出来的属性名进行键值对封装,
然后再看到返回类型是Student对象,再从ResultMap中取出与Student对象匹配的属性名对应的
键值对进行赋值。
resultType 是
-->
<select id="getStudentbyId" parameterType="int"
resultType="Student"> <!-- 直接使用在Mybatis配置文件中定义的类别名 -->
select * from student where id=#{id}
</select>

<!-- 根据一个id 获取一组记录 -->
<select id="getStudents" parameterType="int"
resultMap="list">
select * from student where id >#{id}
</select>
<!-- Student是设置别名后 的类型;resultMap是为了返回list类型而设置的。被上面的select引用
column 为从数据库查询过来的属性,property属性制定了将从数据库查询过来的属性赋值给对象那个属性。
-->
<resultMap type="Student" id="list">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="address" property="address"/>
</resultMap>

<!-- 插入一条记录 ,
id和parameterType  分别与IUserOperation接口中的insertStudent方法的名字和
参数类型一致。以#{name}的形式引用Student参数的name属性,MyBatis将使用反射读取Student参数
的此属性。#{name}中name大小写敏感。引用其他的gender等属性与此一致。useGeneratedKeys设置
为"true"表明要MyBatis获取由数据库自动生成的主键id;keyProperty="id"指定将获取到的主键值注入
到Student的id属性
-->
<insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="id">
INSERT INTO student(name, age, address) VALUES(#{name}, #{age} ,#{address} )
</insert>
<!-- 更新一条记录 -->
<update id="updateStudent" parameterType="Student" >
update student SET name=#{name} , address=#{address} ,age=#{age} where id=#{id}
</update>

<delete id="deleteStudent" parameterType="int">
delete from student where id =#{id}
</delete>

</mapper>


POJO 类

package org.vincent.model;

/**
* 数据库表对应的Java类;POJO对象
*
* @ClassName: Student
* @Description: TODO(这里用一句话描述这个类的作用)
* @author PengRong
* @date 2017年6月16日 上午12:35:37
*
*/
public class Student {
private int id;
private String address;
private String name;
private int age;

public int getId() {
return this.id;
}

public void setId(int id) {
this.id = id;
}

public String getAddress() {
return this.address;
}

public void setAddress(String address) {
this.address = address;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return this.age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Student [id=" + this.id + ", address=" + this.address
+ ", name=" + this.name + ", age=" + this.age + "]";
}

}


接口类

package org.vincent.model;

import java.util.List;

/**
* 只有接口没有实现类,用于Mybatis中查询结果 这里的接口方法名必须和Student.xml中select中id属性一致;
* 比如getStudentbyId 必须和<select id="getStudentbyId" parameterType="int"
* resultType="Student">一致。 不然测试时候报错说不能绑定异常:
* org.apache.ibatis.binding.BindingException: Invalid bound statement (not
* found): org.vincent.model.IStudentOperation.getStudent at
* org.apache.ibatis.binding
* .MapperMethod$SqlCommand.<init>(MapperMethod.java:225) at
* org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:48) at
* org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:65)
* at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58) at
* com.sun.proxy.$Proxy2.getStudent(Unknown Source) at
* org.vincent.mybatisweb.StudentTest.testMutiStudent(StudentTest.java:69) at
* sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
* sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
* at sun.reflect.DelegatingMethodAccessorImpl.invoke(
* DelegatingMethodAccessorImpl.java:43) at
* java.lang.reflect.Method.invoke(Method.java:498) at
* org.junit.runners.model.FrameworkMethod$1
* .runReflectiveCall(FrameworkMethod.java:45) at
* org.junit.internal.runners.model
* .ReflectiveCallable.run(ReflectiveCallable.java:15) at
* org.junit.runners.model
* .FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at
* org.junit.internal
* .runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at
* org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at
* org.junit.runners
* .BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at
* org.junit.
* runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at
* org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at
* org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at
* org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at
* org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at
* org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at
* org.junit.runners.ParentRunner.run(ParentRunner.java:300) at
* org.eclipse.jdt.internal
* .junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at
* org.eclipse
* .jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at
* org.eclipse
* .jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
* .java:467) at
* org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
* RemoteTestRunner.java:683) at
* org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
* .run(RemoteTestRunner.java:390) at
* org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
* .main(RemoteTestRunner.java:197)
*
*
*
* @ClassName: IStudentOperation
* @Description: TODO(这里用一句话描述这个类的作用)
* @author PengRong
* @date 2017年5月16日 上午11:51:04
*
*/

public interface IStudentOperation {
// 查询一个数
public Student getStudentbyId(int id);

// 查询一列数据
public List<Student> getStudents(int id);

// 插入一条记录
public void insertStudent(Student student);

// 更新一条记录
public void updateStudent(Student student);

// 删除一条记录
public void deleteStudent(int id);
}


BaseDao

package org.vincent.dao;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;

public interface BaseDao {
// 公共的日志记录器和配置文件配置在接口中。
public Logger logger = Logger.getLogger(BaseDao.class);
public String MybatisConfig = "mybatis/MybatisConfig.xml";

// 打开一个Session
default public SqlSession getSession() throws IOException {
InputStream inputStream = null;
inputStream = Resources.getResourceAsStream(BaseDao.MybatisConfig);
return new SqlSessionFactoryBuilder().build(inputStream).openSession();
}

// 关闭一个Session
default public void closeSession(SqlSession session) {
if (session != null) {
session.close();
}
}

// 获取一个日志记录器
default public Logger getLogger() {
return BaseDao.logger;
}

}


Student Dao层

package org.vincent.dao;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

import org.apache.ibatis.session.SqlSession;
import org.vincent.model.IStudentOperation;
import org.vincent.model.Student;

import com.mysql.jdbc.StringUtils;

/**
* Student 表的单表增删改查实现,基于接口
*
* @ClassName: StudentInterfaceDaoImpl
* @Description: TODO(这里用一句话描述这个类的作用)
* @author PengRong
* @date 2017年7月23日 上午11:46:00
*
*/
public class StudentInterfaceDaoImpl implements BaseDao, IStudentOperation {
private SqlSession session = null;

public StudentInterfaceDaoImpl() {
try {
this.session = this.getSession();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}// 获取到sqlSession
}

/**
* 关闭Session
*
* @Title: closeSession
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param 设定文件
* @return void 返回类型
* @throws
*/
public void closeSession() {
this.closeSession(this.session);
}

// 通关id和匹配到Student.xml中对应的select标签执行单表查询;没用通关Mapper接口
public Student queryBySql(String sql, int id) {
Student result = null;
if (!StringUtils.isNullOrEmpty(sql)) {
result = this.session.selectOne(sql, id);
} else {
result = null;
}
return result;
}

/**
* 通过一条记录的id根据IStudentOperation接口方法映射到sql mapper文件中一个select标签;获取到一条记录,
*/
@Override
public Student getStudentbyId(int id) {
// TODO Auto-generated method stub
IStudentOperation operation = this.session
.getMapper(IStudentOperation.class);
Student student = operation.getStudentbyId(id);
BaseDao.logger.debug(student);
return student;
}

// 获取到大于指定id的所有记录
@Override
public List<Student> getStudents(int id) {
// TODO Auto-generated method stub
IStudentOperation operation = this.session
.getMapper(IStudentOperation.class);
// ② 通过接口方法获取一组数据库记录
List<Student> list = operation.getStudents(id);
return list;
}

/**
* 根据一个实例student,将对象插入到数据库中。
*/
@Override
public void insertStudent(Student student) {
// TODO Auto-generated method stub
IStudentOperation operation = this.session
.getMapper(IStudentOperation.class);
if (Objects.nonNull(student)) {
operation.insertStudent(student);
} else {
//
}
}

/**
* 更新一条记录的相关属性。
*/
@Override
public void updateStudent(Student student) {
// TODO Auto-generated method stub
IStudentOperation operation = this.session
.getMapper(IStudentOperation.class);
operation.updateStudent(student);
}

/**
* 删除一条数据记录
*/
@Override
public void deleteStudent(int id) {
// TODO Auto-generated method stub
IStudentOperation operation = this.session
.getMapper(IStudentOperation.class);
operation.deleteStudent(id);
}
}


单表增删改查测试类

package org.vincent.mybatisweb;

import java.io.IOException;
import java.util.List;

import org.junit.Test;
import org.vincent.dao.StudentInterfaceDaoImpl;
import org.vincent.model.Student;

/*
* ORM Mybatis 数据库单表  增 删  改 查操作的单元测试
* @ClassName: StudentTest
* @Description: TODO(这里用一句话描述这个类的作用)
* @author PengRong
* @date 2017年6月16日 上午1:10:46
*
*/
public class StudentSingleTableTest {
/**
* 根据一个sqlStatement获取到一条记录;使用selcetOne 函数,通过
* sqlStatement字符串直接映射为Student中对应的SQL语句去执行查询。
*
* @Title: test
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @throws IOException 设定文件
* @return void 返回类型
* @throws
*/
@Test
public void test() throws IOException {
// sqlStatement是根据Student.xml 这个mapper映射文件中namespace+ select
// 的id=getStudentbyId 唯一确定的sql字符串
String sqlStatement = "org.vincent.model.IStudentOperation.getStudentbyId";
StudentInterfaceDaoImpl studentInterfaceDaoImpl = new StudentInterfaceDaoImpl();
System.out.println((studentInterfaceDaoImpl
.queryBySql(sqlStatement, 61)));
studentInterfaceDaoImpl.closeSession();
}

// 通过Id获取一条记录
@Test
public void getStudentbyIdTest() {
StudentInterfaceDaoImpl studentInterfaceDaoImpl = new StudentInterfaceDaoImpl();
// ① 通过接口方法,查询一条数据库 记录。
studentInterfaceDaoImpl.getStudentbyId(2);
studentInterfaceDaoImpl.closeSession();
}

/**
* 用接口的方式编程。这种方式,要注意的一个地方就是。在Student.xml 的映射配置文件中。 mapper节点的
* namespace="org.vincent.model.IStudentOperation" ,
* 命名空间非常重要,不能有错,必须与我们定义的接口全类名一致。如果不一致就会出错,
*
* @Title: testMutiStudent
* @Description: TODO(通过接口方法获取到数据库数据)
* @param
* @throws IOException
* @return void 返回类型
* @throws
*/
@Test
public void getStudentsTest() throws IOException {
StudentInterfaceDaoImpl impl = new StudentInterfaceDaoImpl();
List<Student> list = impl.getStudents(20);
for (Student student : list) {
System.out.println(student);
}
impl.closeSession();
}

/**
* 插入一条数据
*
* @Title: insertStudentTest
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param @throws IOException 设定文件
* @return void 返回类型
* @throws
*/
@Test
public void insertStudentTest() throws IOException {
Student student = new Student();
student.setAddress("深圳市罗湖区红岭北");
student.setAge(27);
student.setName("XX00");
StudentInterfaceDaoImpl impl = new StudentInterfaceDaoImpl();
impl.insertStudent(student);
System.out.println(student);// 能获取到数据库生成得id
impl.closeSession();
}

/**
* 通过id查询一条记录对应的对象,然后更改记录对象,最后通过接口方法更新一条记录
*
* @Title: updateStudent
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param
* @throws IOException
* @return void 返回类型
* @throws
*/
@Test
public void updateStudent() throws IOException {
StudentInterfaceDaoImpl impl = new StudentInterfaceDaoImpl();
Student student = impl.getStudentbyId(60);
student.setAddress("东莞市长安街");
impl.updateStudent(student);
impl.closeSession();
}

/**
* 通过数据库id, 删除一条记录。
*
* @Title: deleteStudent
* @Description: TODO
* @param @throws IOException 设定文件
* @return void 返回类型
* @throws
*/
@Test
public void deleteStudent() throws IOException {
StudentInterfaceDaoImpl dao = new StudentInterfaceDaoImpl();
dao.deleteStudent(59);
dao.closeSession();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐