Mybatis 基本使用(xml篇)
使用到的东西数据库及表的创建mysql -uroot -p123 //根据自己的数据库账号登录,我的账号是root,密码是123.create database learn_java;//创建名为learn_java的数据库use learn_java;//使用创建的数据库//创建用户表CREATE TABLE `user` (`id` int(11) NOT NULL auto_incremen
·
使用到的东西
数据库及表的创建
mysql -uroot -p123 //根据自己的数据库账号登录,我的账号是root,密码是123.
create database learn_java;//创建名为learn_java的数据库
use learn_java;//使用创建的数据库
//创建用户表
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime default NULL COMMENT '生日',
`sex` char(1) default NULL COMMENT '性别',
`address` varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
// 插入表信息
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');
//创建账户表
CREATE TABLE `account` (
`ID` int(11) NOT NULL COMMENT '编号',
`UID` int(11) default NULL COMMENT '用户编号',
`MONEY` double default NULL COMMENT '金额',
PRIMARY KEY (`ID`),
KEY `FK_Reference_8` (`UID`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
//插入表信息
insert into `account`(`ID`,`UID`,`MONEY`) values (1,41,1000),(2,45,1000),(3,41,2000);
maven坐标
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
log4j(log4j.properties)
- 是日志组件,可以不使用它。如果要用,请把它放到resources目录下
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
通过配置XML
- 前置步骤,创建一个maven 项目,然后使用前面说的坐标导入jar包。
简单CRUD(对User表执行)
- 注意点:映射文件和抽象类要同一个目录结构
1、建立User表对应的实体类
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 一个用户有多个账户
private List<Account> accounts;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
2、创建要执行的表操作的接口类,定义要执行的哪些方法
public interface IUserDao {
// 查询所有用户信息
List<User> findAll();
// 增加用户
void saveUser(User user);
// 更新用户信息
void updateUser(User user);
// 删除用户信息
void deleteUser(Integer id);
// 根据名字查询用户信息
List<User> findUserByName(String name);
//查询用户总人数
int getTotal();
// 根据id查询用户
User findUserById(int id);
}
3、配置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>
<!--取别名,默认值是类名。可以简化操作。
原本在映射文件中:parameterType="com.banyu.achieve.xml.dao.User" 现在可以parameterType="user"
-->
<typeAliases>
<!--给这个包下的类都取别名-->
<package name="com.banyu.achieve.xml.domain"/>
</typeAliases>
<!--配置数据库环境-->
<environments default="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/learn_java"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
<!--配置映射文件目录,使用package标签表示在该目录下的所有文件都是映射文件-->
<mappers>
<package name="com.banyu.achieve.xml.dao"/>
</mappers>
</configuration>
4、配置映射文件(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">
<!-- 会以namespace 和 id 在mapper 中查询具体的方法
resultType 表示返回对象的数据类型
parameterType 表示传入的数据对象
id 唯一标识,要与命名空间(抽象方法)中定义的方法名称一致
-->
<mapper namespace="com.banyu.achieve.xml.dao.IUserDao">
<select id="findAll" resultType="com.banyu.achieve.xml.domain.User">
select * from user;
</select>
<insert id="saveUser" parameterType="com.banyu.achieve.xml.domain.User" >
<!-- 将自增id存入user对象中 -->
<selectKey keyColumn="id" resultType="int" order="AFTER" keyProperty="id">
select last_insert_id()
</selectKey>
insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
<update id="updateUser" parameterType="com.banyu.achieve.xml.dao.IUserDao">
update user set username =#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id =#{id}
</update>
<select id="findUserByName" parameterType="String" resultType="user">
<!-- 使用这种会有sql 注入风险 select * from user where username like "%${name}%" -->
<!-- select * from user where username like #{name} -->
select * from user where username like "%${name}%"
</select>
<select id="getTotal" resultType="int" >
select count(*) from user
</select>
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
</mapper>
5、测试类
- 这里使用了 junit 测试包。
public class TestXml {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private IUserDao dao;
@Before
// 执行测试方法之前执行
public void init() throws Exception{
// 读取配置文件
in= Resources.getResourceAsStream("SqlMapConfig.xml");
factory=new SqlSessionFactoryBuilder().build(in);
session=factory.openSession();
dao=session.getMapper(IUserDao.class);
}
@After
// 执行测试方法之后执行
public void destroy() throws Exception{
// 默认是关闭默认提交的
// session.commit();
session.close();
in.close();
}
@Test
public void TestFindAll(){
List<User> users= dao.findAll();
for(User user:users)
System.out.println(user);
}
@Test
public void TestSaveUser(){
User user=new User();
user.setUsername("小老弟");
user.setAddress("北京市东城区");
user.setSex("男");
user.setBirthday(new Date());
// 两次的输出user不一样,后者id已存在
System.out.println(user);
dao.saveUser(user);
System.out.println(user);
}
@Test
public void TestGetTotal(){
System.out.println(dao.getTotal());
}
@Test
public void TestFindUserByName(){
// 这里两个方法于IUserDao.xml中的方法相对应
// List<User> users=dao.findUserByName("%王%");
List<User> users=dao.findUserByName("王");
for(User user:users) System.out.println(user);
}
@Test
public void TestUpdateUser(){
User user=new User();
user.setId(55);
user.setUsername("老大哥");
user.setAddress("北京市西城区");
user.setSex("女");
user.setBirthday(new Date());
dao.updateUser(user);
}
@Test
public void TestDeleteUser(){
dao.deleteUser(55);
}
}
表关系
- 理论上表关系有四种:1对1,1对多,多对1,多对多。
- 实际实现只有两种:1对1,1对多
1、创建account表对应的实体类
public class Account implements Serializable {
private Integer id;
private Integer uid;
private float money;
// 一个账户只能有一个用户(户主)
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public float getMoney() {
return money;
}
public void setMoney(float money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", uid=" + uid +
", money=" + money +
'}';
}
}
2、创建要执行的表操作的接口类,定义要执行的哪些方法
public interface IAccountDao {
// 根据用户id查询账户信息
List<Account> findAccountById(Integer id);
// 查询所有账户及其对应的户主信息
List<Account> findAll();
}
3、1对1(账户对用户,即账户只属于一个用户。IAccountDao.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.banyu.achieve.xml.dao.IAccountDao">
<!--数据库表和实体类之间的映射关系-->
<resultMap id="accountMap" type="account">
<!--id标签表示表的主键-->
<id column="aid" property="id"></id>
<!--result标签表示除主键外的其他列-->
<result column="uid" property="uid"></result>
<result column="money" property="money"></result>
<!-- 这里 association 中 property 对应的是类中的属性 column 对应的是多表连接外键 javaType用于指示user的信息 -->
<association property="user" column="uid" javaType="user" >
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
<result column="address" property="address"></result>
</association>
</resultMap>
<!--这里通过多表查询实现-->
<select id="findAll" resultMap="accountMap">
select u.*,a.id as aid,a.uid,a.money from account a,user u where u.id=a.uid
</select>
<select id="findAccountById" resultType="account">
select * from account where uid = #{id}
</select>
</mapper>
4、1对多(用户对账号,即一个用户可以有多个账户。更新IUserDao.xml中的findAll实现)
<!-- 两种方法都可以使用。第一种方法用于后面的加载测试 -->
<resultMap id="userMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<result property="address" column="address"></result>
<association property="accounts" column="id" select="com.banyu.achieve.xml.dao.IAccountDao.findAccountById"></association>
</resultMap>
<select id="findAll" resultMap="userMap">
select * from user;
</select>
<!-- <resultMap id="userMap" type="user">-->
<!-- <id property="id" column="id"></id>-->
<!-- <result property="username" column="username"></result>-->
<!-- <result property="sex" column="sex"></result>-->
<!-- <result property="birthday" column="birthday"></result>-->
<!-- <result property="address" column="address"></result>-->
<!-- <!–ofType指集合中元素的类型–>-->
<!-- <collection property="accounts" ofType="account">-->
<!-- <id column="aid" property="id"></id>-->
<!-- <result property="uid" column="uid"></result>-->
<!-- <result property="money" column="money"></result>-->
<!-- </collection>-->
<!-- </resultMap>-->
<!-- <select id="findAll" resultMap="userMap">-->
<!-- select u.*,a.id as aid,a.uid,a.money from user u left outer join account a on u.id=a.uid-->
<!-- </select>-->
5、测试类
public class TestRelation {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private IUserDao userDao;
private IAccountDao accountDao;
@Before
public void init() throws Exception{
// 读取配置文件
in= Resources.getResourceAsStream("SqlMapConfig.xml");
factory=new SqlSessionFactoryBuilder().build(in);
session=factory.openSession();
userDao=session.getMapper(IUserDao.class);
accountDao=session.getMapper(IAccountDao.class);
}
@After
public void destroy() throws Exception{
// 默认是关闭默认提交的,即你虽然sql 语句执行成功了,但是它通过事务回滚了。最终结果就是你增删改失败。
session.commit();
session.close();
in.close();
}
@Test
public void TestFindAllAccount(){
List<Account> accounts=accountDao.findAll();
for(Account account:accounts){
System.out.println("--------------");
System.out.println(account);
System.out.println(account.getUser());
}
}
@Test
public void TestFindAllUser(){
List<User> users=userDao.findAll();
for(User user:users){
System.out.println("----------------");
System.out.println(user);
System.out.println(user.getAccounts());
}
}
}
6、注意点:
- collections 用于数组 association 用于单个对象
- 这里是调用了IAccountDa的findAccountById方法进行了子查询。
<association property="accounts" column="id" select="com.banyu.achieve.xml.dao.IAccountDao.findAccountById"></association>
加载
加载方式有两种:
1、直接加载(用到某个对象直接将它整个对象读取出来)
2、懒加载(用到对象的哪个部分就加载哪个部分)
默认是直接加载
- 使用IUserDao.xml中findAll的第一种方式
- 测试类中只获取对象
- 运行的结果如下所示
- 不但打印了所有用户,而且直接进行了用户对应的账户查询
设置为懒加载
在主配置文件(SqlMapConfig.xml)中配置setting标签
再次用测试类测试
只执行了查询所有用户操作,没有对用户有哪些账户信息进行查询。即实现了懒加载。
更多推荐
已为社区贡献1条内容
所有评论(0)