mybatis学习
代理
静态代理
- 我的理解是有一个类(目标类)实现了某个接口,再写另一个代理类也实现了这个接口的方法,该方法里有目标类实现的方法,还有许多服务于这个目标类方法的其他代码。到时候直接接口声明调用实现对象,用代理类的方法实现增强。
- 但这会导致如果有许多接口的功能都需要增强时,每个接口都得写一个代理类,这就会导致代码的冗杂,动态代理由此诞生。
动态代理
JDK动态代理
- 在JDK动态代理中目标对象仍然需要实现相关接口,但代理对象不需要。
- Proxy.newProxyInstance()这个方法可以实现返回一个代理对象,不过里面需要传的参数有点麻烦,一般用一个工厂类写一个方法实现该方法。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
//target为目标类,可以用工厂类构造方法传入
public Object getAgent(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理功能");
Object obj = method.invoke(target,args);
return obj;
}
});
}
CGLib动态代理
- 又叫子类代理,通过在内存中构建子类对象,重写父类的方法实现功能的增强,目标对象可以不实现接口。通过对象字节码框架ASM实现的。
- 被代理的类不能为final,目标对象的方法不能为final和static。
- 工具类Enhancer en =new Enhancer(),en.creater();完成代理对象的创建
三层架构
1.界面层:接收客户端输入,调用业务逻辑层进行处理,返回结果给客户端
2.业务逻辑层:进行整个项目的业务处理,向上为界面层处理结果,向下向数据访问层要数据。
3.数据访问层:专门用来数据库的增删改查,向上为业务逻辑层提供数据
三层架构优点:
- 结构清晰,耦合性低,分工明确
- 可维护,扩展性高
- 利于标准化
- 开发人员可以只关注整个结构某一层的功能实现
- 利于各层逻辑的复用
常用的框架SSM:
- Spring:是整合其他框架的框架,核心是IOC和AOP。
- SpringMVC:是Spring中的一员,专门用来优化控制器(Servlet)的,提供极简单数据提交,数据携带,页面跳转功能
- MyBatis:是持久化层的一个框架,进行数据库访问的优化,专注SQL语句,极大简化了JDBC。
Mybatis实现
- 导入依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
- 指定资源文件(之后打包不会丢失)
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
- 新建properties文件:
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8
jdbc.username =
jdbc.password =
- 新建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>
<properties resource="properties文件名(有后缀)"></properties>
<environments default="development(和下面id对应)">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<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>
<mappers>
<mapper resource="下面的具体Map.xml文件"></mapper>
</mappers>
</configuration>
- 具体Map文件
<?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="hzp">
<select id="getAll" resultType="返回的类所在的package">
select username,password,phone,create_time
from user
</select>
<select id="getByPhone" parameterType="int" resultType="com.nenu.entity.User">
select username,password,phone,create_time
from user
where phone=#{phone}
</select>
<select id="getByName" parameterType="string" resultType="com.nenu.entity.User">
select username,password,phone,create_time
from user
where username like '%${username}%'
//在''中用${},在外用#{}
</select>
</mapper>
- 测试类
public class UserTest {
@Test
public void testGetByPhone() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
User user = sqlSession.selectOne("hzp.getByPhone",1111111);
System.out.println(user);
sqlSession.close();
}
@Test
public void testGetByName() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
List<User> list = sqlSession.selectList("hzp.getByName","ha");
list.forEach(user -> System.out.println(user));
sqlSession.close();
}
}
- 可以进行实体类别名注册
//单类注册
<typeAliases>
<typeAlias type="" alias=""></typeAlias>
</typeAliases>
//批量注册,别名为类名的驼峰命名法
<typeAliases>
<package name="实体类所在包"></package>
</typeAliases>
- 设置日志输出
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
- 动态代理7规范
1.xml文件与实现的接口在同一目录下
2.xml文件与接口的文件名一致,后缀不管
3.xml文件中标签的id值与接口中的方法名一致
4.xml文件中标签的parameterType与接口中方法的参数名一致
5.xml文件中标签的resultType与接口方法返回值一致
6.xml文件的nammespace属性必须是接口的完全限定名称
7.在xml配置文件中注册mapper文件时,使用class==接口的完全限定名称 - 动态代理具体步骤
1.建表
2.建maven工程
3.改目录
4.添加依赖
5.建properties文件到resources目录下
6.添加SqlMapConfig.xml文件
7.添加实体类
8.新建mapper文件夹,建Mapper接口
9.在Mapper文件夹下,建Maper.xml文件,完成增删改查功能
目录
- 可以用注释
//接口方法
List<User> getByNameOrBirthday(
@Param("columnName")
String name,
@Param("columnValue")
String value);
//获取对应的字符串,不过更推荐用map实现
<select id="getByNameOrBirthday" resultType="user">
select *
from user
where ${columnName} like concat('%',#{columnValue},'%');
</select>
其他的一些方法
//username是user类中的username,两者需一样
<select id="getByCondition" parameterType="user" resultType="user">
select <include refid="column"></include>
from user
<where>
<if test="username != null and username != ''">
and username like concat('%',#{username},'%')
</if>
<if test="id != null">
and id = #{id}
</if>
<if test="birthday != null">
and birthday = #{birthday}
</if>
</where>
</select>
//接口中对应方法 List<User> getByArray(Integer []array);
<select id="getByArray" resultType="user">
select <include refid="column"></include>
from user
where id in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
//接口中对应方法List<User> getByMap(Map map),birthdayBegin和birthdayEnd为map中的name
<select id="getByMap" resultType="user">
select *
from user
where birthday between #{birthdayBegin} and #{birthdayEnd};
</select>
//返回多个map
<select id="getMulMap" resultType="map">
select id,username,birthday
from user
where username like concat('%',#{name},'%');
</select>
//update方法
<update id="updateByCondition" parameterType="user">
update user
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="birthday != null">
birthday = #{birthday},
</if>
</set>
where id = #{id}
</update>
//将user和orders表关联,customer有list属性,用collection接收
<resultMap id="customerMap" type="customer">
<id column="id" property="id"></id>
<result property="name" column="username"></result>
<collection property="list" ofType="order">
<id property="id" column="oid"></id>
<result property="uid" column="id"></result>
<result property="num" column="num"></result>
</collection>
</resultMap>
<select id="getByUserId" parameterType="int" resultMap="customerMap">
select u.id,username,o.id oid,o.num
from orders o left join user u on o.uid = u.id
where u.id = #{id}
</select>