mybatis官方介绍
是持久层的框架,支持定制化 SQL、存储过程以及高级映射。
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
可以使用 XML 或注解来配置映射原生信息,将接口和 Java 的 POJO映射成数据库中的记录。
MyBatis官网 http://www.mybatis.org/mybatis-3
最近开始使用 IDEA 工具,具体操作不太熟悉,学习MyBatis同时也顺便学习IDEA的使用。
这篇先对MyBatis的使用简单了解一下。
项目环境搭建
创建项目
首先创建项目,IDEA和Eclipse有所区别,在IDEA中有个Project还有个Model,需要注意这里的Project其实相当于Eclipse中的Workspace,model相当于Eclipse中的一个项目。IDEA可以直接在project中创建项目,也可以在project下创建model,的这种构建方式有利于大项目中的各个model对project中公共资源的利用。
导包
1.手动导包
项目创建好之后需要导入包,初次不使用Maven,手动添加jar包。
先将所需要的jar包在Libraries中添加,取别名为lib,之后在Model中的dependencies中添加library,选择lib。
2.Maven导包
创建一个Maven项目,在pom.xml中添加配置
相关依赖查询 https://mvnrepository.com/artifact/org.mybatis/mybatis
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- <scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
</dependencies>
。
。
。
以下不在正常操作步骤下,有错误时回过来再看
Could not find resource错误
在测试时可能会出现类似错误
java.io.IOException: Could not find resource configuration.xml
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:89)
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:76)
at org.apache.ibatis.io.Resources.getResourceAsReader(Resources.java:134)
解决:使用的是Maven,Maven的项目目录如下
所有的文件都是从 classes 项目主体输出目录开始找。
因此可以完全不使用src/main/resources路径。在类路径的根目录中可以找到xml。直接这样:
<mappers>
<mapper resource="sqlMap/User.xml" />
</mappers>
有关Maven目录参考 http://www.cnblogs.com/haippy/archive/2012/07/05/2577233.html
idea中target目录和out目录有什么区别
-
out存放的是该项目下所有Module(模块)的编译结果。
-
target存放的是单个Module的编译结果。
-
如果为某个Module指定了编译结果的路径,则不会再输出到out文件夹中了。
你在Project Structure中的Project选项卡中可以设置Project compiler output的目录。
在Modules中选择某一个模块后,在右侧的Paths选项卡中可以设置该模块的Compiler output目录。
。
。
。
。
。
。
添加数据库
IDEA需要添加数据库
填写信息完成点击 Test Connection 测试连接 ,在Schemas中选择所需要的数据库。
项目结构
mybatis是持久层框架,完成数据持久化至少需要有POJO类,POJO的映射文件,mybatis的配置文件。
myBatis配置文件
创建 mybatis-config.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">
添加约束,以便在书写过程中检查。
点击加号,输入URI,第二栏选择自己下载的DTD所在路径。
添加约束后书写会很方便
参考官方文档 http://www.mybatis.org/mybatis-3/zh/getting-started.html
<?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="main/resources/jdbc.properties"/>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.DriverClassName}" />
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- Mapper的位置 Mapper.xml 写Sql语句的文件的位置 -->
<mappers>
<mapper resource="main/resources/mapper/User.xml"/>
</mappers>
</configuration>
User
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
}
User.xml
这里也需要添加约束,和之前一样。
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中。
selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常。
具体参考官方文档 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
<?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">
<!--创建映射文件,命名空间区分不同映射文件中相同id的查询-->
<mapper namespace="userMapper">
<!--通过id查询一个用户-->
<!--statement的id是sql的id,paramenterType表明输入的类型,resultType是返回的类型-->
<select id="findUserById" parameterType="int" resultType="main.java.bean.User">
select * from user where id = #{id}/*#占位符里面随便用*/
</select>
<!-- 根据用户名模糊查询-->
<select id="fuzzyQueryByName" parameterType="String" resultType="main.java.bean.User">
/*select * from user where username like '%${value}%' *//*这里只能用value*/
select * from user where username like "%"#{c}"%"
</select>
<!-- 插入数据-->
<insert id="insertUser" parameterType="main.java.bean.User">
<selectKey resultType="int" order="AFTER" keyColumn="id" keyProperty="id">
SELECT last_insert_id()
</selectKey>
insert into user (username,birthday,sex)
values (#{username},#{birthday},#{sex});
</insert>
<!-- 修改数据-->
<update id="updateUser" parameterType="main.java.bean.User">
update user set
username=#{username},
birthday=#{birthday},
sex=#{sex}
where id=#{id}
</update>
<!--删除数据-->
<delete id="deleteUser" parameterType="main.java.bean.User">
delete from user where id=#{id}
</delete>
</mapper>
#{}和${}的区别
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
表 示 拼 接 s q l 串 , 通 过 {}表示拼接sql串,通过 表示拼接sql串,通过{}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, 可 以 接 收 简 单 类 型 值 或 p o j o 属 性 值 , 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值, 可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是value。
业务需求插入数据后返回ID
selectKey设置返回主键ID, last_insert_id()为最后插入的ID,主键类型是int,在Mysql中int型主键是自增的,主键生成是先保存数据之后添加主键,所以 order=“AFTER” ,如果是varchar型数据做主键,则是order=“before” 。
<insert id="insertUser" parameterType="main.java.bean.User">
<selectKey resultType="int" order="AFTER" keyColumn="id" keyProperty="id">
SELECT last_insert_id()
</selectKey>
insert into user (username,birthday,sex)
values (#{username},#{birthday},#{sex});
</insert>
测试程序
测试程序步骤:
- 创建SqlSessionFactoryBuilder对象
- 加载SqlMapConfig.xml配置文件
- 创建SqlSessionFactory对象
- 创建SqlSession对象
- 执行SqlSession对象执行查询,获取结果User
- 打印结果
- 释放资源
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
SqlSessionFactory
一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。只有一个实例化对象。
SqlSession
每个线程都应该有它自己的 SqlSession 实例。不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。
public class MyBatisTest {
private final static SqlSessionFactory sqlSessionFactory;
//加载配置文件
//在这里对SqlSessionFactory进行创建,后面只需要调用即可。
static {
String resource = "main/resources/mybatis-config.xml";
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
} catch (IOException e) {
e.printStackTrace();
}// 创建SqlSessionFactoryBuilder对象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
根据ID查找
@Test
public void findUserByIdTest() throws Exception {
//创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//执行sql语句
try {
/*执行SqlSession查询,第一个参数是User.xml中的ststement的id,第二个是sql执行的参数*/
User user = sqlSession.selectOne("userMapper.findUserById", 1);
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
根据姓名模糊查询
@Test
public void fuzzyQueryByNameTest() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
List<User> list = sqlSession.selectList("userMapper.fuzzyQueryByName", "张");
for (User u : list) {
System.out.println(u.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
插入数据
@Test
public void insertUserTest() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User u = new User();
u.setUsername("baoluo");
u.setBirthday(new Date());
u.setSex("男");
int i = sqlSession.insert("userMapper.insertUser", u);
System.out.println(i);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
修改数据
@Test
public void updateUserTest() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User u = new User();
u.setId(28);
u.setUsername("baoluoluo");
u.setBirthday(new Date());
u.setSex("男");
sqlSession.update("userMapper.updateUser",u);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
删除数据
@Test
public void deleteUserTest() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
User u = new User();
u.setId(28);
sqlSession.delete("userMapper.deleteUser",u);
sqlSession.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
到此基本上就可以实现数据的增删改查了。
我在运行时出现过这个问题
关闭一次防火墙后就好了,也不知道是什么原因。