Mybatis的CRUD操作
最基本的增删改查:
UserDao接口
/**
* 用户持久层接口
*/
public interface IUserDao {
// @Select("select * from user")
List<User> findAll();
void saveUser(User user);
void updateUser(User user);
void deleteUser(Integer id);
User findById(Integer id);
}
IUserDao.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="com.dyz.dao.IUserDao">
<!--配置查询所有-->
<select id="findAll" resultType="com.dyz.domain.User">
select * from user
</select>
<insert id="saveUser" parameterType="com.dyz.domain.User">
<!--配置插入数据后,获取插入数据的id-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user (username,address,sex,birthday) value (#{username},#{address},#{sex},#{birthday});
</insert>
<update id="updateUser" parameterType="com.dyz.domain.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};
</update>
<delete id="deleteUser" parameterType="Integer">
delete from user where id=#{id};
</delete>
<select id="findById" parameterType="Integer" resultType="com.dyz.domain.User">
select * from user where id=#{id};
</select>
</mapper>
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER"></selectKey>:
插入数据后返回被插入数据的行id,keyProperty="id"属性表示实体类中的id,keyColumn返回结果集中的id,parameterType传入的参数类型,
resultType返回值值类型,order属性表示插入之后。
test测试类
package com.dyz;
import com.dyz.dao.IUserDao;
import com.dyz.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
* mybatis的入门案例
*/
public class test {
private InputStream in;
SqlSession sqlSession;
IUserDao userDao;
@Before
public void inti() throws IOException {
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After
public void destroy() throws IOException {
//6.释放对象
sqlSession.close();
in.close();
}
/**
* 查询所有
*
*/
@Test
public void testFindAll(){
// UserDaoImp userDaoImp = new UserDaoImp(factory);
// List<User> users = userDaoImp.findAll();
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user:users){
System.out.println(user);
}
}
/**
* 添加用户
*/
@Test
public void testSave(){
User user = new User();
user.setUsername("sanxiang");
user.setAddress("xiangtan");
user.setSex("男");
user.setBirthday(new Date());
userDao.saveUser(user);
sqlSession.commit();
}
/**
* 更新用户
*/
@Test
public void testUpdate(){
User user = new User();
user.setId(2);
user.setUsername("zhongkui");
user.setAddress("shaoyang");
user.setSex("男");
user.setBirthday(new Date());
userDao.updateUser(user);
sqlSession.commit();
}
/**
* 删除用户
*/
@Test
public void testDelete(){
userDao.deleteUser(3);
sqlSession.commit();
}
/**
* 根据id查询用户
*/
@Test
public void testFindOne(){
User user = userDao.findById(2);
System.out.println(user);
}
}
模糊查询:
Statement对象的字符串拼接SQL方式:
@Test
public void testFindByName(){
List<User> users = userDao.findByName("耶");
for (User user:users){
System.out.println(user);
}
}
<select id="findByName" parameterType="String" resultType="com.dyz.domain.User">
select * from user where username like '%${value}%'
</select>
执行信息:
PrepatedStatement的参数占位符方式:
@Test
public void testFindByName(){
List<User> users = userDao.findByName("%耶%");
for (User user:users){
System.out.println(user);
}
}
<select id="findByName" parameterType="String" resultType="com.dyz.domain.User">
<!--此处name为任意值,可以改变-->
select * from user where username like #{name}
</select>
执行信息:
以上两种模糊查询的方式在实际开发中,PrepatedStatement的参数占位符方式使用较多。Statement对象的字符串拼接SQL方式有SQL注入隐患。
传递POJO包装对象
IUserDao接口
List<User> findUserByVo(Queryvo vo);
Queryvo实体类
public class Queryvo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
映射文件
<select id="findUserByVo" parameterType="com.dyz.domain.Queryvo" resultType="com.dyz.domain.User">
select * from user where username like #{user.username}
</select>
测试方法
@Test
public void testFindUserByVo(){
Queryvo queryvo = new Queryvo();
User user = new User();
user.setUsername("%z%");
queryvo.setUser(user);
List<User> userByVo = userDao.findUserByVo(queryvo);
for (User u:userByVo){
System.out.println(u);
}
}
resultMap结果类型
MySql数据库在window系统下不区分大小写,在linux系统下严格区分大小写。Java严格区分大小写。
当开发过程中或二次中实体类的属性名字段与数据库中定义的属性字段名不一致时,mybatis无法将属性名不一致的字段自动对应,此时就需要将从数据库中查询到的结果集属性名与程序中的实体类属性相对应。具体有以下两种方式:
1.通过在数据库查询语句中起别名的方式,使返回的结果集属性名与实体类中的属性名一致。
2.在映射文件中配置resultMap标签,使之对应。
实体类user:
package com.dyz.domain;
import java.util.Date;
public class User {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}
1.数据库查询语句中起别名的方式:
映射文件:
<!--配置查询所有-->
<select id="findAll" resultType="com.dyz.domain.User">
select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user ;
</select>
此方式是通过数据库语句的形式使返回结果集与实体类对于,执行效率较高。
2.在映射文件中配置resultMap标签的方式:
映射文件:
<!-- 配置查询结果的列名和实体类的属性名的对应关系-->
<resultMap id="userMap" type="com.dyz.domain.User">
<!--主键字段对应-->
<id property="userId" column="id"></id>
<!--非主键字段的对应-->
<result property="userName" column="username"></result>
<result property="userAddress" column="address"></result>
<result property="userSex" column="sex"></result>
<result property="userBirthday" column="birthday"></result>
</resultMap>
<!--配置查询所有-->
<select id="findAll" resultMap="userMap">
select * from user
</select>
注意事项:
:id为唯一标识符,可以为任意值。type为对应的实体类。
:id标签对应表的主键,property属性对应实体类中的字段属性名,column对应查询结果集的属性名字段。
:id对应接口类中的方法名,resultMap属性对应配置的resultMap标配签的唯一标识符。
此方式提高了开发者的开发效率,但需要多解析一个xml配置,执行效率有所降低。
Properties标签的使用及细节
mybatis的主配置文件:
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>
<!-- 配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置链接数据库的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
<property name="username" value="root"/>
<property name="password" value="tiger"/>
</dataSource>
</environment>
</environments>
<!--指定映射文件的位置,映射配置文件指的是每个dao独立的配置文件
如果是用注解来配置,此处应该使用class属性指定被注解的dao全限定类名-->
<mappers>
<mapper resource="com/dyz/dao/IUserDao.xml" />
<!--<mapper class="com.dyz.dao.IUserDao"/>-->
</mappers>
</configuration>
使用properties标签:
<?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属性(常用):resource="jdbcConfig.properties"
用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下
URL属性: url="file:///C:/Users/DYZ/Desktop/mybatis01_eesy/src/main/resources/jdbcConfig.properties"
要求按照url的写法来写地址
URL:Uniform Resource Locator统一资源定位符,它可以唯一标识一个资源的位置
http://localhost:8080/mybatis/demo
协议 主机 端口 URL
URI:Uniform Resource Identifier统一资源标识符,它是在应用中可以唯一定位一个资源的
-->
<properties >
<!--配置链接数据库的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"/>
<property name="username" value="root"/>
<property name="password" value="tiger"/>
</properties>
<!-- 配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置链接数据库的四个基本信息-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--指定映射文件的位置,映射配置文件指的是每个dao独立的配置文件
如果是用注解来配置,此处应该使用class属性指定被注解的dao全限定类名-->
<mappers>
<mapper resource="com/dyz/dao/IUserDao.xml" />
<!--<mapper class="com.dyz.dao.IUserDao"/>-->
</mappers>
</configuration>
使用外部jdbcConfig.properties配置文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/eesy
jdbc.username=root
jdbc.password=tiger
此时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属性(常用):resource="jdbcConfig.properties"
用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下
URL属性:url="file:///C:/Users/DYZ/Desktop/mybatis01_eesy/src/main/resources/jdbcConfig.properties"
要求按照url的写法来写地址
URL:Uniform Resource Locator统一资源定位符,它可以唯一标识一个资源的位置
http://localhost:8080/mybatis/demo
协议 主机 端口 URL
URI:Uniform Resource Identifier统一资源标识符,它是在应用中可以唯一定位一个资源的
-->
<properties resource="jdbcConfig.properties"></properties>
<!-- 配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置链接数据库的四个基本信息-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--指定映射文件的位置,映射配置文件指的是每个dao独立的配置文件
如果是用注解来配置,此处应该使用class属性指定被注解的dao全限定类名-->
<mappers>
<mapper resource="com/dyz/dao/IUserDao.xml" />
<!--<mapper class="com.dyz.dao.IUserDao"/>-->
</mappers>
</configuration>
typeAliases标签配置别名:
<!--使用typeAliases配置别名,它只能配置domain(实体类)中类的别名-->
<typeAliases>
<!--typeAlias用于配置别名,type属性指定的是实体类全限定类名,alias属性指定别名,当指定了别名将不再区分大小写-->
<!--<typeAlias type="com.dyz.domain.User" alias="user"></typeAlias>-->
<!--用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.dyz.domain"></package>
</typeAliases>
在主配置 文件中使用typeAliases标签配置别名后,在dao的映射文件中需要需要使用实体类的全限定名时,可直接使用别名。
使用package标签指定映射文件位置
<!--指定映射文件的位置,映射配置文件指的是每个dao独立的配置文件
如果是用注解来配置,此处应该使用class属性指定被注解的dao全限定类名-->
<mappers>
<!--<mapper resource="com/dyz/dao/IUserDao.xml" />-->
<!--<mapper class="com.dyz.dao.IUserDao"/>-->
<!--package标签用于指定dao接口所在的包,当指定了之后就不需要再写mapper以及resource或者class了-->
<package name="com.dyz.dao"></package>
</mappers>