文章目录
一、JDBC问题总结
1.数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。使用数据库连接池可以解决此问题;
2.SQL语句写在代码中,所以想修改SQL需要修改源代码,不易维护;
3.使用PreparedStatement向占位符号传参数存在固定代码,SQL语句的where条件可能会变化,造成要修改代码,从而不易维护;
4.对结果集解析存在固定代码,SQL变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成POJO对象解析比较方便。
二、Mybatis架构
三、Mybatis入门程序
1、环境搭建及通过ID查询示例
在数据库中创建表:
语句:
CREATE TABLE `user` (
`id` BIGINT(32) AUTO_INCREMENT,
`username` VARCHAR(32),
`birthday` VARCHAR(32),
`sex` VARCHAR(32),
`address` VARCHAR(32),
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
表结构:
创建工程:Javaproject
导入jar包:与src平行的位置创建一个文件夹lib,将要导入的jar包放进去,再Build Path
创建映射类:User.java(极其get、set方法,这里省略)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用户姓名
private String sex;//性别
private String birthday;// 生日
private String address;// 地址
}
创建核心配置文件: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>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="2e5y8hxf" />
</dataSource>
</environment>
</environments>
<!--映射的位置-->
<mappers>
<mapper resource = "sqlXml/User.xml"/>
</mappers>
</configuration>
创建映射配置文件:User.xml
parameterType:输入参数类型,可以是简单数据类型、pojo对象、pojo包装对象
resultType:输出结果类型
命名空间namespace:用于存在多个配置映射时进行区分;
#{}:表示占位符,相当于select * from user where id = ? 中的?
<?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">
<!-- 写SQL语句 -->
<mapper namespace = "user_test">
<!-- 通过ID查询一个用户 -->
<select id="findUserById" parameterType = "Integer" resultType = "pojo.User">
select * from user where id = #{v}
</select>
</mapper>
创建日志文件:log4j.properties用具显示记录的程序运行过程
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
创建测试类文件:
public class TestDemo1 {
@Test
public void demo1() throws Exception {
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行SQL语句
User user = sqlSession.selectOne("user_test.findUserById", 1);
System.out.println(user);
}
}
测试结果:
2、通过用户名模糊查询
修改映射配置文件:
${}:表示字符串拼接,相当于select * from user where username like ‘% ${value} %’ ,这里{}内必须为value;
另一种写法:select * from user where username like “%”#{haha}"%" ,这里的#{haha}相当于’haha’;
<?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">
<!-- 通过用户名模糊查询 -->
<select id="findUserByUsername" parameterType = "String" resultType = "pojo.User">
select * from user where username like '%${value}%'
</select>
</mapper>
修改测试类:
public class TestDemo1 {
@Test
public void demo1() throws Exception {
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行SQL语句
List<User> users = sqlSession.selectList("user_test.findUserByUsername","三");
for(User user:users)
System.out.println(user);
}
}
测试结果:
3、添加用户并返回添加的用户ID
1.添加用户:
修改映射配置文件:
<?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">
<!-- 写SQL语句 -->
<mapper namespace = "user_test">
<!-- 添加用户 -->
<insert id="insertUser" parameterType = "pojo.User">
insert into user(username,birthday,address,sex)
values (#{username},#{birthday},#{address},#{sex})
</insert>
</mapper>
修改测试类:
@Test
public void demo2() throws Exception {
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行SQL语句
User user = new User();
user.setUsername("张无忌");
user.setBirthday("1650年0101");
user.setAddress("武当山");
user.setSex("男");
int i = sqlSession.insert("user_test.insertUser",user);
sqlSession.commit();
}
测试结果:
2.返回添加的用户ID:
修改映射配置文件:
<!-- 添加用户 -->
<insert id="insertUser" parameterType = "pojo.User">
insert into user(username,birthday,address,sex)
values (#{username},#{birthday},#{address},#{sex})
</insert>
修改测试类:
System.out.println(user.getId());
测试结果:
按照最新添加的用户,输出其id值。
4、通过ID修改用户
修改映射配置文件:
<?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">
<!-- 写SQL语句 -->
<mapper namespace = "user_test">
<!-- 更新用户 -->
<update id="updateUserById" parameterType = "pojo.User">
update user set username = #{username},sex = #{sex},birthday = #{birthday},address = #{address}
where id = #{id}
</update>
</mapper>
修改测试类:
@Test
public void demo3() throws Exception {
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行SQL语句
User user = new User();
user.setId(3);
user.setUsername("赵敏");
user.setBirthday("1650年0101");
user.setAddress("元大都");
user.setSex("女");
int i = sqlSession.update("user_test.updateUserById",user);
sqlSession.commit();
}
测试结果:
5、通过ID删除用户
修改映射配置文件:
<?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">
<!-- 写SQL语句 -->
<mapper namespace = "user_test">
<!-- 删除用户 -->
<update id="deleteUserById" parameterType = "Integer">
delete from user where id = #{hahaha}
</update>
</mapper>
修改测试类:
@Test
public void demo4() throws Exception {
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行SQL语句
sqlSession.delete("user_test.deleteUserById",3);
sqlSession.commit();
}
测试结果:删除了ID为3的用户。
四、Mybatis与Hibernate区别
概述:Mybatis和Hibernate不同,它不完全是一个ORM框架,Hibernate完全是ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
区别一:Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发;
区别二:Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。
五、原始DAO开发和Mapper动态代理开发
1、原始DAO开发
注意:这里省略User.xml和sqlMapConfig.xml文件的编写;
创建UserDao接口和实现类:在DAO中注入工厂,并与数据库建立联系;
public interface UserDao { //接口
public User selectUserById(Integer id);
}
public class UserDaoImpl implements UserDao{ //实现类
//注入工厂
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super();
this.sqlSessionFactory = sqlSessionFactory;
}
//通过ID查询一个用户
@Override
public User selectUserById(Integer id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession.selectOne("user_test.findUserById",id);
}
}
创建测试类:这里创建DAO之后,没有创建Service层,所以使用Junit测试代替。在测试类中创建Session工厂,然后将工厂作为入参,创建DAO对象,之后就可以使用userDao进行查询操作了。
public class MybatisDaoTest {
public SqlSessionFactory sqlSessionFactory;
@Before
public void before() throws Exception{
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
}
@Test
public void demo1() throws Exception{
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
User user = userDao.selectUserById(2);
System.out.println(user);
}
}
2、Mapper动态代理开发
注意:这里省略User.xml和sqlMapConfig.xml文件的编写;
编写动态代理接口:
遵循四个原则:
(1)Mapper接口方法名与映射配置文件Mapper.xml(这里为User.xml)中相应statement的id名一致;
(2)Mapper接口中的输出参数类型与Mapper.xml中的定义的每个sql的resultType的类型相同;
(3)Mapper接口中的输入参数类型与Mapper.xml中的定义的每个sql的parameterType的类型相同;
(4)将Mapper.xml命名空间namespace设置为接口的类路径名,绑定此接口。
User.xml为:
代理接口代码为:
public interface UserMapper {
public User findUserById(Integer id);
}
编写测试类:
@Test
public void demo1() throws Exception {
//加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
//创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlSession帮我生成一个实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
}
测试结果:
两点注意:
1.针对selectOne和selectList说明:
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法;
2.namespace说明
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类。
六、sqlMapConfig.xml核心配置文件分析
SqlMapConfig.xml中配置的内容和顺序如下:标签可以省略不配置,但是顺序不能变;
1、properties(属性标签)
概述:位于configuration子标签下的属性标签,用于填充value值;
使用properties标签前:
使用properties标签后:
在src目录下建立jdbc.properties文件:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_01?characterEncoding=utf-8
jdbc.username=root
jdbc.password=2e5y8hxf
2、typeAliases(别名标签)
第一种方式:直接将pojo.User起一个别名叫User,可以在User.xml(映射配置文件)中直接使用User;
<typeAliases>
<typeAlias type="pojo.User" alias = "User"/>
</typeAliases>
第二种方式:可以在User.xml(映射配置文件)中直接使用pojo包里所以的类名;
<typeAliases>
<package name="pojo"/>
</typeAliases>
使用方式:
另外,Mybatis支持的别名:
3、mappers(属性标签)
1.mapper子标签:
第一种方式:使用resource
<mappers>
<mapper resource = "sqlXml/User.xml"/>
</mappers>
第二种方式:使用class,此方法也要求Mapper代理中的接口名称与映射文件名称一致,且放在同一目录下(即:通过Mapper代理接口来找到UserMapper.xml(映射配置文件,即前面的User.xml),前提是该接口与xml文件的名字相同,这里是都为UserMapper)。
<mappers>
<mapper class = "mapper.UserMapper"/>
</mappers>
第三种方式:使用url,要求绝对路径,一般不用。
2.package字标签:此方法也要求Mapper代理中的接口名称与映射文件名称一致,且放在同一目录下,这里为mapper目录,企业中一般用这种方式。
<mappers>
<package name = "mapper"/>
</mappers>