框架是一件半成品软件,里面封装了很多细节,程序员在这已有的半成品基础上再加上我们自己的业务需求进去,就变成了一件完整的成品软件,好比框架就是一个舞台,舞台已经有了,接下来该怎么表演就看你的业务需求是什么。所以说在开发时,框架帮我们做了一半的工作,封装了很多的细节,使得我们可以更加关注在业务逻辑的实现上,而不是去纠结一些细枝末节的问题,提高开发效率。
一般为了方便管理,我们会把整个项目分为三层,我们要学的MyBatis框架就在三层中的持久层中起作用
JDBC技术:
Connection:获取数据库的连接
PreparedStatement:执行sql语句
ResultSet:封装与数据库交互后返回的数据
Spring的JdbcTemplate:spring中对JDBC的简单封装,相对于上面直接用JDBC起来要方便不少
Apache的DBUtils:它和spring的JdbcTemplate很像,也是对jdbc的简单疯转
但是以上的都不是框架,JDBC是java与数据库交互的规范,和框架根本就谈不上关系;JdbcTemplate和DBUtils就有点封装的意味了,但这只是简单的封装,并没有像框架一样提供一套完整的解决方案,只能说是一个工具类而已。
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","root", "root");
//定义 sql 语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理 statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
反思:在上面的代码中,其实我们仅仅是想实现一条sql语句,就是下面这一条
String sql = "select * from user where username = ?";
但是却写了很多的代码作为这条语句的准备工作,比如加载驱动、创建连接、创建preparedStatement,还有善后工作,比如关闭连接资源、关闭preparedStatement,是真的很…,Mybatis框架的出现,让我们得以从这些冗余的工作中解放出来,而仅仅只需关注sql语句本身就行了
mybatis是一个持久层框架,是java编写的,它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,它使用了ORM思想实现了结果集的封装
Object Relational Mapping:对象关系映射
简单来说:就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就可以实现操作数据库表
比如我在数据库中有一张表叫user表,而在java类中对应有一个User类
数据库中的user表 | java中的User类 |
---|---|
username | userName |
id | Id |
数据库的user表中的username和User类中的userName属性是对应的,我们操作User类的时候就相当是在操作数据库中的user表,这就是映射。
在这里我导入了四个jar包,其中mybatis和mysql相关的jar包是必须要有的
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.stfgroupId>
<artifactId>day01artifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.6version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.12version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.10version>
dependency>
dependencies>
project>
1. 数据库中创建一个user表,这个user表我放在一个名叫mybatis的数据库里面
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','女','北京修正');
2. 创建一个User类
package domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
//对应上图user表中的id
private Integer id;
//对应上图user表中的username
private String username;
//对应上图user表中的birthday
private Date birthday;
//对应上图user表中的sex
private String sex;
//对应上图user表中的address
private String address;
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 + '\'' +
'}';
}
}
1. 创建dao接口UserDao
package dao;
import domain.User;
import java.util.List;
/**
* 用户的持久层接口
*/
public interface UserDao {
/**
* 查询所有操作
* @return
*/
List<User> findAll();
}
1. 在resources文件夹中创建Mybatis的主配置文件
注意:我这里的mysql密码是root,用户也是root,访问的数据库是mybatis
<configuration>
<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/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="/dao/UserDao.xml"/>
mappers>
configuration>
<mapper namespace="dao.UserDao">
<select id="findAll" resultType="domain.User">
select * from user
select>
mapper>
创建UserDao的映射文件时,很多人是把映射文件起名为UserMapper.xml的,我这里把它叫为UserDao.xml也是可以的。
Mybatis的映射配置文件位置必须和dao接口的包结构相同,比如我在dao文件夹下创建了一个UserDao.java,那就要在dao文件夹下创建UserDao.xml或UserMapper.xml
映射配置文件的mapper标签namespaces属性的取值必须是dao接口的全限定类名
映射配置文件的id属性的取值必须是dao接口的方法名,因为我这里是查询操作,所以是select id = ,这里的resultType是查询后返回的类型,必须是全限定类名
这个本来在环境搭建的时候就加进去的,如果没加的话,是看不到日志信息的,会出现红色的
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
现在我把这个配置文件添加在resource目录下
log4j.properties
# 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
在测试文件夹test文件夹下创建一个MybatisTest类
import dao.UserDao;
import domain.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
/**
* Mybatis的入门案例
* @param args
*/
public static void main(String[] args) throws IOException {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象,代理操作,不需要创建实现类
UserDao userDao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
/* 运行结果:
User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
User{id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}
User{id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙'}
User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}
User{id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京'}
User{id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正'}
*/
我们可以看到在入门案例的介绍中,虽然说是只关注sql语句本身就行了,但是还是很麻烦,还要特别关注映射文件的写法,不能写错,又要加载配置文件、创建工厂等等,似乎并不是特别方便。
但初学者的话,写得详细一点,多一点,更有利于我们学习,而且现在只是用Mybatis框架而已,等将来再学几个框架,框架一组合起来,我们就会发现真的仅仅只是关注sql语句本身已经足够了。
用注解的方式来替代xml文件,显然会写得更少
第一步:在UserDao.java文件中加上注解@Select,并指定要执行的sql语句
第二步:删除刚才创建的UserDao.xml文件,因为有了注解,已经不需要它了
第三步:在主配置文件SqlMapConfig.xml中更改mapper标签
注意:在实际开发中,一般是越简便越好,所以一般不写xml映射文件,而采用注解的方式来弄,也不会自己去写实现类,但是出于学习的目的,我们接下来还是尝试一下自己写实现类的方式,而不采用代理对象
第一步:创建UserDao的实现类UserDaoImpl
import domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
public class UserDaoImpl implements UserDao {
private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory factory){
this.factory = factory;
}
public List<User> findAll() {
//1.使用工厂创建SqlSession对象
SqlSession session = factory.openSession();
//2.使用session执行查询所有方法,其实这个selectList里面可以写sql语句的,但是
//如果写sql语句的话,那UserDao接口里面的注解不就完全没意义了吗,既然我们把sql
//语句写在接口方法findAll的注解上了,那么我们找到这个方法就行
List<User> users = session.selectList("dao.UserDao.findAll");
session.close();
//3.返回查询结果
return users;
}
}
第二步:修改测试类MybatisTest
因为我们用自己的实现类来实现,就不再用代理对象了
修改后的实现类
import dao.UserDao;
import dao.impl.UserDaoImpl;
import domain.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
public static void main(String[] args) throws IOException {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.创建UserDao接口的实现类对象
UserDao userDao = new UserDaoImpl(factory);
//4.执行实现类里面的findAll方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//5.释放资源
in.close();
}
}
运行,发现结果是正确的
为了能看到更多一点信息,这次的CRUD操作将采用xml映射文件的方式,而不是注解
因为测试时要创建工厂、获取SqlSession、获取代理对象,如果在测试查找方法、测试删除方法等等方法里面都要重复地创建工厂、获取对象,就会非常麻烦,而且用完还要释放资源。
我们不如创建一个init函数,专门用来创建工厂、获取对象的
创建一个destroy方法,专门用来释放资源的,这样就会让代码看起来简洁一点,比如测试类可以这样写
import dao.UserDao;
import domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.omg.IOP.ComponentIdHelper;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private UserDao userDao;
@Before //用于测试方法之前自动执行
public void init() throws IOException {
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession();
//4.获取dao的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
@After //用于测试方法之后自动执行
public void destory() throws IOException {
//5.提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
/**
* 测试查询所有
*/
@Test
public void testFindAll() throws IOException {
//5.执行查询方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
}
第一步:在UserDao.java文件中增添保存方法:saveUser
/**
* 保存用户
* @param user
*/
void saveUser(User user);
第二步:在UserDao.xml中映射该方法
<insert id="saveUser" parameterType="domain.User">
insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
insert>
第三步:在测试类MybatisTest中添加测试:testSave
/**
* 测试保存操作
*/
@Test
public void testSave(){
User user = new User();
user.setUsername("mybatis.saveuser");
user.setAddress("广东省广州市");
user.setSex("男");
user.setBirthday(new Date());
//保存用户
userDao.saveUser(user);
}
注意:保存用户中有一个细节,因为用户id在数据库是采用自增长的形式的,存进去前user是没有id的,但是一存到数据库后,数据库表就会给这个user分配一个id,我们可以通过select last_insert_id()获得这个id,并把它set在user里面,select last_insert_id()总的解释就是 将插入数据的主键返回到 user 对象中,我们来实验下
首先, xml文件改成下面这样
<insert id="saveUser" parameterType="domain.User">
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
selectKey>
insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
insert>
然后,测试类这样写,目的是为了看user对象在执行saveUser方法的前后有没有多了个id值
@Test
public void testSave(){
User user = new User();
user.setUsername("mybatis.saveuser");
user.setAddress("广东省广州市");
user.setSex("男");
user.setBirthday(new Date());
//user是没有设置id属性的,现在的 id 默认是null
System.out.println("保存操作之前:" + user);
//保存用户
userDao.saveUser(user);
//看看user现在id是不是有值了
System.out.println("保存操作之后:" + user);
//输出结果可以看到id由null变成了54
}
第一步:在UserDao.java文件中增添更新方法:updateUser
/**
* 更新,修改用户
* @param user
*/
void updateUser(User user);
第二步:在UserDao.xml中映射该方法
<update id="updateUser" parameterType="domain.User">
update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};
update>
第三步:在测试类MybatisTest中添加测试:testUpdateUser
/**
* 测试更新操作
*/
public void testUpdateUser(){
User user = new User();
user.setId(41);
user.setUsername("update");
user.setAddress("广东省广州市");
user.setSex("女");
user.setBirthday(new Date());
//更新用户
userDao.updateUser(user);
}
第一步:在UserDao.java文件中增添更新方法:deleteUser
/**
* 根据ID删除用户
* @param userId
*/
void deleteUser(Integer userId);
第二步:在UserDao.xml中映射该方法
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid};
delete>
第三步:在测试类MybatisTest中添加测试:testDeleteUser
/**
* 测试删除操作
*/
@Test
public void testDeleteUser(){
//根据Id删除用户
userDao.deleteUser(41);
}
第一步:在UserDao.java文件中增添更新方法:findById
/**
* 根据ID查找用户
* @param userId
*/
User findById(Integer userId);
第二步:在UserDao.xml中映射该方法
<select id="findById" parameterType="java.lang.Integer" resultType="domain.User">
select * from user where id = #{uid};
select>
第三步:在测试类MybatisTest中添加测试:testFindUserById
/**
* 根据Id查找用户
*/
@Test
public void testFindUserById(){
User user = userDao.findById(42);
System.out.println(user);
}
第一步:在UserDao.java文件中增添更新方法:findByName
/**
* 根据名字模糊查找
* @param username
* @return
*/
List<User> findByName(String username);
第二步:在UserDao.xml中映射该方法
<select id="findByName" parameterType="java.lang.String" resultType="domain.User">
select * from user where username like #{usernmae};
select>
第三步:在测试类MybatisTest中添加测试:testFindByName
/**
* 根据username进行模糊查询
*/
@Test
public void testFindByName(){
List<User> users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
注意:这里有个小细节就是,当模糊查找需要加两个百分号时,比如上面的(%王%),这是在测试类中加的百分号,也可以在xml文件中的映射选项加,那么把UserDao.xml下面的语句
select * from user where username like #{usernmae};
改成这样
select * from user where username like ‘%${value}%’;
同时测试类中也无需自己添加百分号
List<User> users = userDao.findByName("王");
但是改成这样的话,不大好这样子做的话,在底层中是调用的是statement方法,而不是preparestatement,因为statement采用的是拼接字符串的形式完成sql语句的,拼接字符串带来的一个潜在问题就是sql注入,属于危险操作!
第一步:在UserDao.java文件中增添更新方法:findTotal
/**
* 寻找总的用户条数
* @return
*/
int findTotal();
第二步:在UserDao.xml中映射该方法
<select id="findTotal" resultType="java.lang.Integer">
select count(*) from user;
select>
第三步:在测试类MybatisTest中添加测试:testFindTotal
/**
* 根据username进行模糊查询
*/
@Test
public void testFindTotal(){
int count = userDao.findTotal();
System.out.println(count);
}
Mybatis框架支持OGNL表达式,它的字面意思就是:
Object Graphic Navigation Language
对象 图 导航 语言
它是通过对象的取值方法来获取数据的,在写法上把get给省略了,比如:我们获取用户名称
平时写法是:user.getUsername
ONGL表达式:user.username
Mybatis中为什么能直接写username,而不用user呢,比如
select * from user where username like #{usernmae};
它根本就不用写user.getUsername,因为parameterType已经提供了属性所属的类,所以不需要写对象名
<select id="findByName" parameterType="java.lang.String" resultType="domain.User">
假如parameterType没有直接提供属性所属的类,那就可以用OGNL表达式的写法
我们试着重写一下模糊查询方法findByName
第一步:封装User类
package domain;
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
第二步:在UserDao.java中添加方法fundByVo
/**
* 根据OGNL表达式进行模糊查找
* @param vo
* @return
*/
List<User> findByVo(QueryVo vo);
第三步:在xml文件中映射该方法
注意:parameterType那里写的不再是domain.User类了,
<select id="findByVo" parameterType="domain.QueryVo" resultType="domain.User">
select * from user where username like #{user.username};
select>
第四步:编写测试方法
/**
* 根据OGNL表达式进行模糊查询
*/
@Test
public void testFindByVo(){
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%王%");
vo.setUser(user);
List<User> users = userDao.findByVo(vo);
for (User u : users) {
System.out.println(u);
}
}
OGNL也常应用在开发中,当由多个对象组成一个查询条件时,OGNL表达式就会起很大作用,OGNL表达式的字面意思已经说白了,就是对象导航语言,当有多个对象凑在一起时,仍然能方便清晰地找到
package domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
//对应数据库user表中的id
private Integer id;
//对应数据库user表中的username
private String username;
//对应数据库user表中的birthday
private Date birthday;
//对应数据库user表中的sex
private String sex;
//对应数据库user表中的address
private String address;
//各种getter和setter
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
..........
}
之所以能够操作数据库,是因为User类中的属性和数据库表中的列名是对应关系的,Javabean中的属性指的就是getter方法去掉get剩下的部分,比如getId(),属性就是Id;还有setter方法去掉set剩下的部分,比如setId,属性就是Id,但是MySql数据库中的那个是id,怎么就能对应上呢?注意,Windows系统下的MySQL是不区分大小写的,写Id和写id是一样的。那现在由于某种原因,我决定改动javabean,改动后的属性与数据库中的user表列名不一致了
package domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer userId;
private String name;
private String userAddress;
private String userSex;
private Date userBirthday;
//属性是UserId,而数据库中的是id,不一致
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
//属性是Name,而数据库中的是username,不一致
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//属性是UserAddress,而数据库中的是address,不一致
public String getUserAddress() {
return userAddress;
}
..........
}
因为数据库中的属性和java类中的属性没办法对应上了,所以再用原来xml映射是无法完成查询所有操作的
之前的xml写的是
<select id="findAll" resultType="domain.User">
select * from user
select>
select * from user执行了之后,没办法进行封装返回,因为返回类型是User类,但是属性不一致就不能够把查询到的信息封装到User中返回。
我们可以把xml中的映射信息改成
<select id="findAll" resultType="domain.User">
select id as userId, username as name, address as userAddress, sex as userSex, birthday as userBirthday from user
select>
测试类中测试一下
/**
* 测试查询所有
*/
@Test
public void testFindAll() throws IOException {
//5.执行查询方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
}
结果是正常的,证明封装成功了
起别名之后,User类属性和数据库表属性就又能对应上了,而且起别名的效率是最高的,因为这是深入到sql语句层面上进行的改动,但是也很麻烦,好多方法都要这样起别名,万一我以后又要改动User类了呢,又要起…
在UserDao.xml中配置属性关系,就是查询结果的列名和实体类属性的列名的对应关系
UserDao.xml
<resultMap id="userMap" type="domain.User">
<id property="userId" column="id">id>
<result property="Name" column="usernmae">result>
<result property="userAddress" column="address">result>
<result property="userSex" column="sex">result>
<result property="userBirthday" column="birthday">result>
resultMap>
<select id="findAll" resultMap="userMap">
select * from user;
select>
然后再调用测试方法,发现封装结果没有问题
以上内容是我观看传智播客视频所做笔记