文章目录
1.dao层的CRUD操作:以前userdao都是用jdbc template实现,现在换成Mybatis,需要一个sqlsession对象
1.1 dao
package com.itheima.dao;
import com.itheima.domain.User;
public interface UserDao {
public void addUser(User user);
public void update(User user);
public User findUserById(int id);
public void deleteById(int id);
}
package com.itheima.dao.impl;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import org.apache.ibatis.session.SqlSession;
public class UserDaoImpl implements UserDao {
private SqlSession sqlSession; //sqlSession现在是空值,以前直接=new jdbctemplate...
//现在不是new一下能搞定的,要1.获取资源,2.解析配置,3.创建工厂对象,4.sqlSession。如下通过构造传入。
public void setSqlSession(SqlSession sqlSession) {
//传递赋值,构造和set方法都可以
this.sqlSession = sqlSession;
}
@Override
public void addUser(User user) {
sqlSession.update("UserDaoMapper.addUser",user); //ibatis会自动将user映射成sql需要的参数
}
@Override
public void update(User user) {
sqlSession.update("UserDaoMapper.update",user);
}
@Override
public void deleteById(int id) {
sqlSession.update("UserDaoMapper.deleteById",id);
}
@Override
public User findUserById(int id) {
User user = sqlSession.selectOne("UserDaoMapper.findUserById", id); //返回user对象
return user;
}
}
1.2 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">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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="UserMapper.xml"/>
<mapper resource="UserDaoMapper.xml"></mapper>
</mappers>
</configuration>
1.3 UserDaoMapper.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="UserDaoMapper">
<select id="findUserById" resultType="com.itheima.domain.User">
select * from tb_user where id = #{id}
</select>
<insert id="addUser"> <!-- user对象的属性-->
insert into tb_user(user_name,password,name) values(#{userName},#{password},#{name})
</insert>
<delete id="deleteById">
delete from tb_user where id=#{id}
</delete>
<update id="update">
update tb_user set age=#{age},sex=#{sex} where id = #{id}
</update>
</mapper>
1.4 domain
package com.itheima.domain;
import java.util.Date;
public class User {
private Long id;
private String userName; // 用户名
private String password; // 密码
private String name; // 姓名
private Integer age; // 年龄
private Integer sex; // 性别,1男性,2女性
private Date birthday; // 出生日期
private Date created; // 创建时间
private Date updated; // 更新时间
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", birthday=" + birthday +
", created=" + created +
", updated=" + updated +
'}';
}
}
1.5 test
如上选中按ctrl+shift+t产生如下:
package com.itheima.dao;
import com.itheima.dao.impl.UserDaoImpl;
import com.itheima.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.Before;
import org.junit.Test;
import java.io.InputStream;
import static org.junit.Assert.*;
public class UserDaoTest {
private UserDaoImpl userDao = new UserDaoImpl();
@Before
public void setUp() throws Exception {
//创建sqlSession
InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); //获取io流对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //工厂对象
SqlSession sqlSession = sqlSessionFactory.openSession(true); //true表示自动提交事务
userDao.setSqlSession(sqlSession);
}
@Test
public void addUser() {
User user = new User();
user.setPassword("123666");
user.setName("王思聪1");
user.setUserName("wangsicong1");
userDao.addUser(user);
}
@Test
public void update() {
User user = new User();
user.setId(10l);
user.setAge(30);
user.setSex(1);
userDao.update(user);
}
@Test
public void findUserById() {
User user = userDao.findUserById(10);
System.out.println(user);
}
@Test
public void deleteById() {
userDao.deleteById(10);
}
}
如下或者在.openSession里写true。
2.动态代理Dao实现:userDao对象改为userMapper对象
发现每个dao层sqlSession.insert等每个方法底层都是update实现都是一样的,只是参数不一样,所以可以把方法都写一样。只有接口情况下,mybatis帮我们创造实现类UserDaoImpl
即动态代理,调用mybatis方法创建的接口类型对象。
mybatis动态代理方式需要遵循以下约定即namespace和id限制
1. 一个接口对应一个mapper文件 【默认】
2. 映射文件中的命名空间(名称控制)与 接口的全路径 一致
3. 映射文件中的statement的Id与 接口的方法名 保持一致
4. 映射文件中的statement的ResultType必须和mapper接口方法的返回类型一致(即使不采用动态代理,也要一致)【默认】
如下2,3对应上面2,3。
如下dao文件夹名称换成mapper文件夹。
2.1 mapper
package com.itheima.mapper;
import com.itheima.domain.User;
public interface UserMapper {
public User findUserById(int id);
public void deleteById(int id);
}
2.2 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">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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="UserMapper.xml"/>
</mappers>
</configuration>
2.3 UserMapper.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.itheima.mapper.UserMapper">
<!--
mybatis动态代理开发重点规范:
1 namespace必须和接口的全路径保证一致
2 sql语句的id必须和方法名保证一致
-->
<select id="findUserById" resultType="com.itheima.domain.User">
select * from tb_user where id = #{id}
</select>
</mapper>
2.4 test
package com.itheima.mapper;
import com.itheima.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.Before;
import org.junit.Test;
import java.io.InputStream;
import static org.junit.Assert.*;
public class UserMapperTest {
private UserMapper userMapper; //声明但未new创建
@Before
public void setUp() throws Exception {
//创建userMapper对象
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFacoty = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFacoty.openSession();
userMapper = sqlSession.getMapper(UserMapper.class); //底层是动态代理(只有接口情况下,创建接口类对象)
}
@Test
public void findUserById() {
User user = userMapper.findUserById(1); //userMapper对象
System.out.println(user);
}
}
所以只需要一个UserMapper接口就行。
3.动态代理底层原理:接口名和方法名
package com.itheima.proxy;
import com.itheima.mapper.UserMapper;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MapperProxy {
//工具类
public static UserMapper getProxyMapper(){
//提供一个方法,创建接口对象的动态代理对象的
/*
参数1:类加载器,任意一个类加载器即可。
参数2: 被代理对象UserMapper实现的接口。
参数3:处理器
*/
ClassLoader classLoader = UserMapper.class.getClassLoader();
Class[] classes = new Class[1]; //只有一个UserMapper接口就可以
classes[0]=UserMapper.class;
UserMapper proxyUserMapper = (UserMapper) Proxy.newProxyInstance(classLoader, classes, new InvocationHandler() {
/**
* @param proxy 代理对象本身,没用。
* @param method 将要执行的方法
* @param args 方法需要的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//mybatis框架规范:1.namespace必须是接口的全限定名。2.statement的id就是接口的方法名。
String methodName = method.getName(); //获取将要执行的方法的名字
String nameSpace = UserMapper.class.getName();
String statementId= methodName;
String sqlId = nameSpace+"."+statementId;
System.out.println("将要执行的sql语句的唯一标识是:"+sqlId);
// sqlSession.update(sqlId,args);
return null;
}
});
return proxyUserMapper;
}
public static void main(String[] args) {
UserMapper userMapper = getProxyMapper();
userMapper.findUserById(1);
// userMapper.deleteById(1); //运行的是invoke方法
}
}
如上打印出如下就是UserMapper.xml中namespace.方法名。
如下所以mybatis要设计一套规范,让调用者遵循规范写。
如下日志:
package com.itheima.log4j;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
public class Log4jTest {
private static Logger logger = LogManager.getLogger(Log4jTest.class);
public static void main(String[] args) {
/**
* 日志从低到高6个级别,中间4个常见
* trace< debug<warn<info<error <fatal
*/
logger.trace("trace");
logger.debug("debug");
logger.warn("warn");
logger.info("info");
logger.error("error");
}
}
B站/知乎/微信公众号:码农编程录