mybatis
jdbc编程
- 优点:
- 编程简单
- 效率高
- 缺点:
- 数据库的连接频繁的关闭,造成资源的浪费。
解决方案: 数据库的连接池(dbcp c3p0…) - sql语句存在硬编码,如果要修改需求,那就要修改sql语句,而sql语句又是在java代码中,我们改变了Java代码就要重新编译java代码,不易于维护。解决方案:(设想—>不要写在java代码中)
- 数据库的连接频繁的关闭,造成资源的浪费。
mybatis的架构
SqlMapConfig(配置信息的封装对象)—>SqlSessionFactory(连接池对象)—>SqlSession(一个连接对象)—>Excecutor(执行)—>mapstatement(sql语句的封装对象)
mybatis概念?
- 持久层(dao)的解决方案
- 解决了jdbc硬编码与连接对象频繁创建的问题
mybatis入门程序
修改maven编译jdk的版本
conf/settings.xml
<profiles>
<profile>
<id>development-jdk-1.8</id>
<activation>
<jdk>1.8</jdk>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
mybatis依赖的pom
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
配置日志文件(暂时忽略)
创建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="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/up2"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sqlmap/UserMapper.xml"></mapper>
</mappers>
</configuration>
创建映射(mapper)文件
<?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="test">
<select id="findUserById" parameterType="int" resultType="int">
<!--只有一个参数尽量用#{value}-->
select age from user where id=#{id}
</select>
</mapper>
运行程序
- 创建配置文件SqlMapConfig,用来初始化SqlSessionFactory对象
- 创建编写sql语句的xml文件(映射文件)
- 创建SqlSessionFactory对象
- 创建SqlSession对象
- 使用SqlSession对象执行MapStatement(对映射文件的封装)
public class Main {
public static void main(String[] args) {
//1.创建SqlSessionFactory的对象
InputStream resourceAsStream = Main.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//2.创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//有一个查询结果用selectOne,多个用selectList
Object o = sqlSession.selectOne("test.findUserById", 1);
System.out.println(o);
}
}
常用参数
- UserMapper.xml中的namespace 命名空间(表示一组MapStatement)
- id:一个statement的唯一标识
- parameterType:输入参数的类型(java中的数据类型或者mybatis中的数据类型)
- resultType:输出参数的类型(java中的数据类型或者mybatis中的数据类型),只是指定类型,和查询出来的数量无关
解决mybatis中查询中文出现的问题(8.x以下的版本)
<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/up2&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
查询多条记录
/**使用 selectOne(id,param);查询的结果如果是多条则会出现一些错误,使用selectList(id)即可查询多条记录
*/
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2
模糊查询
<!--想象的模糊查询-->
<select id="findUserByNameOfLike" parameterType="string" resultType="com.lyx.mybatis.pojo.User">
select * from user where name like #{name}
</select>
<!--想象的模糊查询是存在问题的,因为参数一般是用户输入的,用户会输入通配符 % _吗? -->
<!--改进之后变成以下这样了-->
<select id="findUserByNameOfLike" parameterType="string" resultType="com.lyx.mybatis.pojo.User">
select * from user where name like '%#{name}%'
</select>
改进方案
<select id="findUserByNameOfLike" parameterType="string" resultType="com.uplooking.mybatis.pojo.User">
select * from user where name like "%${value}%"
</select>
<select id="findUserByNameOfLike" parameterType="string" resultType="com.uplooking.mybatis.pojo.User">
select * from user where name like "%"#{name}"%"
</select>
${} 与 #{}
-
#{} 以占位符的形式进行填充(可以避免sql注入,推荐使用)
-
${} 以普通字符串的形式进行填充
添加用户
<insert id="addUser" parameterType="com.uplooking.mybatis.pojo.User">
INSERT into user VALUES (null,#{name},#{age})
</insert>
public void testAddUser() {
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setName("小红");
user.setAge(29);
sqlSession.insert("test.addUser", user);
sqlSession.commit();
sqlSession.close();
}
mybatis与hibernate的区别
11.1 mybatis
- 入门简单,程序容易上手开发,节省开发成本
- mybatis需要程序员自己编写sql语句 是一个不完全 的ORM(对象关系映射,创建了一个可在编程语言里使用的“虚拟对象数据库”)框架 ,对sql修改和优化非常容易实现
- mybatis适合开发需求变更频繁的系统,比如:互联网项目
11.2 hibernate
- 入门门槛高 ,如果用hibernate写出高性能的程序不容易实现。hibernate不用写sql语句
- hibernate适合需求固定,对象数据模型稳定,中小型项目,比如:企业OA系统。
总之,企业在技术选型时根据项目实际情况,以降低成本和提高系统 可维护性为出发点进行技术选型。
mybatis开发dao
传统的方式开发dao
定义接口
public interface UserMapper {
User selectById(Integer id);
List findBySex(String sex);
}
实现类
public class UserMapperImpl implements UserMapper {
private SqlSessionFactory sqlSessionFactory;
public UserMapperImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
public User selectById(Integer id) {
SqlSession sqlSession = sqlSessionFactory.openSession(true);
User user = sqlSession.selectOne("test.findUserById",id);
return user;
}
public List findBySex(String sex) {
SqlSession sqlSession = sqlSessionFactory.openSession(true);
List list = sqlSession.selectList("test.selectBySex",sex);
return list;
}
}
测试类
public class Main {
public static void main(String[] args) {
//1.创建SqlSessionFactory的对象
InputStream resourceAsStream = Main.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
UserMapper userMapper = new UserMapperImpl(sqlSessionFactory);
List<User> userList = userMapper.findBySex("女");
System.out.println(userList);
}
}
使用mapper代理的方式开发dao
程序员只需要写dao接口,dao接口实现对象由mybatis自动生成代理对象
相比传统的方式开发更加简单,且传统的dao开发中存在硬编码(statement_id)
使用mapper代理的方式开发dao层要遵循一些规范:
- Mapper接口必须和映射文件在同一个目录下
- mapper.xml中namespace指定为mapper接口的全限定名
- mapper.xml中statement的id就是mapper.java中方法名
- mapper.xml中statement的parameterType和mapper.java中方法输入参数类型一致
- mapper.xml中statement的resultType和mapper.java中方法返回值类型一致.
创建mapper接口
public interface UserMapper {
User selectById(Integer id);
List<User> selectBySex(String sex);
}
创建mapper.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.lyx.mapper.UserMapper">
<!--parameterType传进来的类型 resultType返回类型-->
<select id="selectById" parameterType="java.lang.Integer" resultType="com.lyx.entity.User">
select * from user where id=#{value}
</select>
<select id="selectBySex" parameterType="java.lang.String" resultType="com.lyx.entity.User">
select * from user where sex=#{value}
</select>
</mapper>
配置SqlMapConfig
<mappers>
<package name="com.lyx.mapper"/>
</mappers>
maven不认识mapper.xml解决方案
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
测试运行
public class Main {
public static void main(String[] args) {
//1.创建SqlSessionFactory的对象
InputStream resourceAsStream = Main.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//2.创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//3.返回由jdk底层生成的代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//4.执行业务方法
User user = mapper.selectById(1);
System.out.println(user.getName());
}
}