创建数据库,用户表
create table user (
id int(10) auto_increment,
username varchar(20),
account varchar(20),
password varchar(20),
email varchar(20),
primary key(id)
);
insert into user values (null,'小明','xiaoming,'xiaoming','xiaoming@qq.com');
导入jar包
mybatis-3.2.7.jar // Mybatis的核心jar包
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-log4j12-1.7.5.jar //Mybatis核心包的依赖包
mysql-connector-java-5.1.28-bin.jar //数据库连接驱动
查询所有的用户信息
创建JavaBean(User)
package com.luhui.bean;
public class User {
private Integer id;
private String username;
private String password;
private int age;
private String sex;
//空参构造、有参构造
//getter 、setter
}
编写全局配置文件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>
<!--项目上线时使用的数据源 -->
<!-- <environment id="running">
。。。
</environment> -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value= "jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--映射文件,即含有sql语句的xml文件 -->
<mapper resource="com/luhui/mapper/UserMapper.xml"/>
</mappers>
</configuration>
注:配置环境:数据源、事物
-
environments:可以在该标签中配置数据源和事物的管理等,可配置多个。
-
envirment:配置具体的数据源和事务。
-
id:每个environment都有自己的 id,用于和其他数据源进行区分。
-
default:值就是environment标签中的id,用于决定最终使用的数据源
-
transactionManager:配置事物,事物有JDBC和MANAGER两种类型:
-
JDBC:事物将由JDBC处理
-
MANAGER:代表用户自己管理,后期可将事物交给Spring处理
-
dataSource:POOLED/UNPOOLED/JNDI
-
POOLED:使用数据库连接池化
-
UNPOOLED:不使用数据库连接池
-
JNDI:另外一种数据库的连接方式,不需要理会
注意:该配置文件中 标签的顺序是固定的。这里必须先写transactionManager,再写dataSource。
编写映射文件UserMapper.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"> <!--配置映射文件: (1)namespace: 命名空间,是用来唯一区分Mapper文件的属性, 一般取值为对应dao层接口(UserDao)的全限定名称 全限定名称:即类的 包名+类名 (2)MyBatis的配置文件中,有分别对应增删改查的四种标签,分别是:insert、delete、update、select id:唯一区分该条语句的属性 resultType: 返回类型是List<User>。 注意:MyBatis中,如果需要的返回类型为集合,则只需要填写集合中元素的类型 (3)注意:MyBatis的sql语句中不能添加 ";" --> <!-- <mapper>:根元素 namespace:命名空间 作用:唯一识别映射文件的属性 写法:一般取值为对应dao层接口(UserDao)的全限定名称:包名+类名 MyBatis的配置文件中,有分别对应增删改查的四种标签,分别是:insert、delete、update、select <select>:MyBatis查询标签,所有的查询语句都只能写在这里 id:方法的唯一标识。命名空间+id能唯一指定sql语句 resultType:MyBatis只关心结果集Map<User>、List<User>中存放的元素的类型(User)。即MyBatis中,如果需要的返回类型为集合,则只需要填写集合中元素的类型 在更新、删除和新增操作中,只能返回int类型,此时不需要再表明返回类型 parameterType:参数类型,在sql语句中插入参数的格式 #{value} value是活的 --> <mapper namespace="com.luhui.mapper.UserDao"> <select id="selectAllUser" resultType="com.luhui.bean.User"> select * from user </select> </mapper>
通过SqlSession对象进行CRUD的操作
package com.luhui.test;
import java.io.InputStream;
import java.util.List;
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 com.luhui.bean.User;
public class Test {
@Test
public void test01() throws IOException {
//1:获取会话工厂SqlSeesionFactory
String resource = "sqlMapConfig.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//2:通过工厂对象产生会话
SqlSession sqlSession = factory.openSession();
//3:通过会话进行增删改查
List<User> userAll = sqlSession.selectList("com.luhui.mapper.UserDao.selectAllUser");
System.out.println(userAll);
//4:关闭会话
sqlSession.close();
}
}
代码优化
上述代码中,有可以重复使用的代码:创建SqlSessionFactory对象和SqlSession对象。所以根据Java中封装的思想,可以将这些代码封装到一个方法或者类中,进行直接调用。但是 SqlSessionFactory是线程安全的,而SqlSession是非线程安全的。所以只能将获取SqlSessionFactory对象的代码进行封装,而SqlSession不能封装。
package com.luhui.Util;
public class SqlSessionFactoryUtils {
private final static Class<SqlSessionFactoryUtils> LOCK = SqlSessionFactoryUtils.class ;
private static SqlSessionFactory sqlSessionFactory;
public static SqlSessionFactory getSqlSessionFactory() {
synchronized (LOCK) {
if (sqlSessionFactory != null) {
return sqlSessionFactory;
}
String resource = "sqlMapConfig.xml";
InputStream inputStream;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (Exception e) {
return null ;
}
return sqlSessionFactory;
}
}
public static SqlSession openSqlSession( ) {
if (sqlSessionFactory == null) {
getSqlSessionFactory();
}
return sqlSessionFactory.openSession();
}
}
测试代码
@Test
public void test02() throws IOException {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
List<User> userAll = sqlSession.selectList ("com.luhui.mapper.UserDao.selectAllUser");
System.out.println(userAll);
sqlSession.close();
}
根据id操作单条记录
查询:在UserMapper.xml文件中的标签中添加:
<select id="selectById" resultType="com.luhui.bean.User" parameterType="int">
select * from user where id = #{id}
</select>
测试代码:
@Test
public void test03() throws IOException {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
User user = sqlSession.selectOne("com.luhui.mapper.UserDao.selectById",1);
System.out.println(user);
sqlSession.close();
}
因为是根据用户id查询,所以需要传递参数。测试类中,调用的方法需要两个参数User user = sqlSession.selectOne("com.luhui.mapper.UserDao.selectById",1)
。在映射文件中,需要使用parameterType标签属性来表明参数的类型,该属性的值是MyBatis自己定义的数据类型,和数据库中的数据类型一一对应:
MyBatis中数据类型 Java数据类型
int Integer
string String
map、 java.util.Map Map
list、 java.util.List List
在MyBatis的sql语句中,需要将参数插入sql语句中:MyBatis规定参数引入格式为:#{value}。
修改:在UserMapper.xml文件中的标签中添加:
<update id="updateById" parameterType="com.luhui.bean.User">
update user set username = #{username} ,account=#{account} , password = #{password},email = #{email} where id =#{id}
</update>
测试代码:
@Test
public void test04(){
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
User user=new User(1,"小四","123456",18,"1");
int num = sqlSession.update("com.luhui.mapper.UserDao.updateById", user);
System.out.println(num);
sqlSession.commit();
sqlSession.close();
}
如果传递的参数类型为Map,则取值方式相同。但是参数类型parameterType=“map”。这里的更新操作需要调用commit()方法提交,否则数据库将不会被更新。
<update id="updateByMap" parameterType="map">
update user set username = #{username} ,account=#{account},password = #{password},email = #{email} where id =#{id}
</update>
测试代码:
package com.luhui.test;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.luhui.util.MyBatisUtil;
public class Test {
public static void main(String[] args) {
SqlSessionFactory factory = MyBatisUtil.getSqlSessionFactory();
SqlSession sqlSession = factory.openSession();
Map map = new HashMap();
map.put("id", 2 );
map.put("username", "张三");
map.put("account", "zhs");
map.put("password", "123456");
map.put("email", "zhs@qq.com");
int num = sqlSession.update ("com.luhui.mapper.UserDao.updateByMap", map);
System.out.println("影响的行数:"+num);
sqlSession.commit();
sqlSession.close();
}
}
模糊查询
首先回忆一下Mysql的模糊查询语法,根据用户名的关键字查询用户,sql语句:
SELECT * FROM user WHERE username LIKE "%张%";
在MyBatis中,参数(张)需要插入sql语句中,此时需要使用${value}的格式拼接。注意一般参数使用#{value}的格式。
在UserMapper.xml文件中的标签中添加:
<select id="selectByLike" parameterType="string" resultType="com.luhui.bean.User">
select * from user where username like '%${value}%'
</select>
测试代码:
@Test
public void test05() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
List<User> users= sqlSession.selectList("com.luhui.mapper.UserDao.selectByLike", "小");
System.out.println(users);
sqlSession.commit();
sqlSession.close();
}
MyBatis的动态代理
前面例子中,我们都是使用Sqlsession接口进行发送SQL语句,这里我们使用MApper接口来发送SQL语句,即Mybatis的动态代理。MyBatis的动态代理方式只需要遵循一定的规则,即可避免对接口的实现。代码简单,是官方推荐并且实际开发中使用的方式。
1)Dao层接口的全限定名要和mapper映射文件的namespace值一致(使mapper.xml和mapper.Java进行关联)。
2)mapper.xml中sql语句的id就是接口中的方法名。
3)接口的方法参数类型要和mapper映射文件的parameterType的值一致。
4)Dao接口的方法返回值类型要和映射文件的statement的resultType的值一致。
package com.luhui.mapper;
public interface UserDao {
public List<User> selectAllUser();
public User selectById(int id);
public int updateById(User user);
public List<User> selectByLike(String username);
}
测试代码
@Test
public void test06() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> users= userDao.selectAllUser();
System.out.println(users);
User user= userDao.selectById(1);
System.out.println(user);
sqlSession.commit();
sqlSession.close();
}
2.5、使用注解对表操作
在接口UserDao.Java中添加:
@Select("select * from user where username = #{username}")
public User selectByUsername(String username);
测试:
@Test
public void test07() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user= userDao.selectByUsername("张三");
System.out.println(user);
sqlSession.commit();
sqlSession.close();
}
注:若它和XML方式同时使用时,XML方式将覆盖注解方式。一般我们都是使用XML方式,因为当SQL比较复杂的时候,会降低代码可读性,以及若使用动态SQL的时,不利于维护和修改。