Mybatis的注解开发
这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper
映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
MyBatis用注解实现增删改查
- 编写User实体
public class User {
private int id;//用户id
private String username;//用户名
private String password;//密码
//省略set和get方法及ToString方法
}
- 编写UserMapper接口
public interface UserMapper {
//增
@Insert("insert into user (id,username,password) value (#{id}, #{username}, #{password})")
void save(User user);
//删
@Delete("delete from user where id = #{id}")
void delete(int id);
//改
@Update("update user set username = #{username}, password = #{password} where id = #{id}")
void update(User user);
//根据id查
@Select("select * from user where id = #{id}")
User findById(int id);
//查找全部
@Select("select * from user")
List<User> findAll();
}
- 编写核心配置文件
这里要注意 :
Mapper 加载的不是映射文件,因为使用的是注解,所以没有映射文件;
Mapper 加载的是映射关系,即 UserMapper 接口,可以使用mapper扫描接口,也可以用package扫描类所在的包
<configuration>
<!--jdbc配置文件-->
<properties resource="jdbc.properties"/>
<!--定义别名-->
<typeAliases>
<typeAlias type="com.xiafanjun.domain.User" alias="user"/>
</typeAliases>
<!--配置数据库环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--配置映射-->
<!--<mappers>
加载配置文件
<mapper resource="com/xiafanjun/mapper/userMapper.xml"/>
</mappers>-->
<!--加载映射关系-->
<mappers>
<!--扫描接口-->
<!--<mapper resource="com.xiafanjun.mapper.UserMapper"/>-->
<!--扫描接口所在的包-->
<package name="com.xiafanjun.mapper"/>
</mappers>
</configuration>
- 编写测试方法
public class MybatisTest {
private UserMapper userMapper;
//加载配置文件
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
//增
@Test
public void testSave(){
User user = new User();
user.setUsername("zhangsan");
user.setPassword("738sdfj");
userMapper.save(user);
}
//删
@Test
public void testDelete(){
userMapper.delete(1);
}
//改
@Test
public void testUpdate(){
User user = new User();
user.setId(7);
user.setUsername("wanwu");
user.setPassword("738903");
userMapper.update(user);
}
//通过id查找
@Test
public void findById(){
User user = userMapper.findById(2);
System.out.println(user);
}
//User{id=2, username='lucy', password='abcde'}
//查找全部
@Test
public void findAll(){
List<User> userList = userMapper.findAll();
for(User user:userList){
System.out.println(user);
}
}
/*
User{id=1, username='tom', password='123456'}
User{id=2, username='lucy', password='abcde'}
User{id=3, username='jack', password='xyz'}
User{id=4, username='zhangsan', password='qwerew'}
User{id=5, username='xiafanjun', password='abcdefg'}
User{id=6, username='lisi', password='hskdne'}
User{id=7, username='wanwu', password='738903'}
*/
}
MyBatis的注解实现复杂映射开发
实现复杂关系映射之前我们可以在映射文件中通过配置来实现,使用注解开发后,我们可以使用@Results注解
,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
注解 | 说明 |
---|---|
@Results | 代替的是标签< resultMap >该注解中可以使用单个@Result注解,也可以使用@Result集 合。使用格式:@Results({@Result(),@Result()})或@Results(@Result()) |
@Resut | 代替了< id >标签和< result >标签 @Result中属性介绍: column:数据库的列名 property:需要装配的属性名 one:需要使用的@One 注解(@Result(one=@One)())) many:需要使用的@Many 注解(@Result(many=@many)())) |
@One (一对一) | 代替了< assocation > 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。 @One注解属性介绍: select: 指定用来多表查询的 sqlmapper 使用格式:@Result(column=" “,property=”“,one=@One(select=”")) |
@Many (多对一) | 代替了< collection >标签, 是多表查询的关键,在注解中用来指定子查询返回对象集合。 使用格式:@Result(property=“”,column=“”,many=@Many(select=“”)) |
一对一查询
1. 一对一查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户
2. 一对一查询的语句
对应的sql语句:
select * from orders;
select * from user where id=查询出订单的uid;
期望查询出的结果
3. 创建Order和User实体
Order实体
public class Order {
private int id;//订单id
private String orderTime;//订购时间
private double total;//价格
private User user;//代表当前订单从属哪一个客户
//省略set和get方法及ToString方法
}
User实体
public class User {
private int id;//用户id
private String username;//用户名
private String password;//密码
//省略set和get方法及ToString方法
}
4. 创建OrderMapper接口
public interface OrderMapper {
List<Order> findAll();
}
5. 使用注解配置Mapper
public interface OrderMapper {
@Select("select * from orders")
@Results({
//id=true表明是主键
@Result(id = true,column = "id",property = "id"),
@Result(column = "ordertime",property = "orderTime"),
@Result(column = "total",property = "total"),
@Result(column = "uid",//根据哪个字段去查询user表中的数据
property = "user",//要封装的属性名称
javaType = User.class,//要封装的实体类型
//UserMapper接口中的findById方法,相当于将uid传入到该方法中
one = @One(select = "com.xiafanjun.mapper.UserMapper.findById"))
})
List<Order> findAll();
}
6. 测试结果
public class OrderMapperTest {
private OrderMapper orderMapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession(true);
orderMapper = sqlSession.getMapper(OrderMapper.class);
}
@Test
public void findAll(){
List<Order> orderList = orderMapper.findAll();
for(Order order:orderList){
System.out.println(order);
}
}
}
一对多查询
1. 一对多查询的模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
2. 一对多查询的语句
对应的sql语句:
select * from user;
select * from orders where uid=查询出用户的id;先查出user表中的数据,再根据user表中的id查找order表
期望查询出的结果
3. 修改User实体
public class User {
private int id;//用户id
private String username;//用户名
private String password;//密码
private List<Order> orderList;//代表当前用户具备那些订单
//省略set和get方法及ToString方法
}
4. 创建UserMapper接口
List<User> findAllUserAndOrder();
5. 使用注解配置Mapper
因为要通过Order中的uid来查找user相应的order,所以在OrderMapper中添加findByUid方法
@Select("select * from orders where uid=#{uid}")
Order findByUid(int uid);
UserMapper中的方法
@Select("select * from user")
@Results({
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(column = "id",property = "orderList",
javaType = List.class,
//一对多的查询用many
many = @Many(select = "com.xiafanjun.mapper.OrderMapper.findByUid"))
})
List<User> findAllUserAndOrder();
6. 测试结果
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void findAllUserAndOrder(){
List<User> allUserAndOrder = userMapper.findAllUserAndOrder();
for(User user:allUserAndOrder){
System.out.println(user);
}
}
多对多查询
1. 多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用
多对多查询的需求:查询用户同时查询出该用户的所有角色其实多对多的查询与一对多的查询差不多,只是中间多了一张关系表
2. 多对多查询的语句
对应的sql语句:
select * from user;
select * from role r,user_role ur where r.id=ur.role_id and ur.user_id=用户的id先查询出user表中的数据,再通过user表中的id,在user_role中查询出对应的roleid,在用roleid在role表中查出相应的角色名称
期望查询出的结果: select * from user u,user_role ur,role r where u.id = ur.userid and ur.roleid = r.id
3. 创建Role实体,修改User实体
创建Role实体
public class Role {
private int id;//角色id
private String rolename;//角色名
//省略set和get方法及ToString方法
}
修改User实体
public class User {
private int id;//用户id
private String username;//用户名
private String password;//密码
private List<Order> orderList;//代表当前用户具备那些订单
private List<Role> roleList;// 代表当前用户具备哪些角色
//省略set和get方法及ToString方法
}
4. 添加UserMapper接口方法
List<User> findAllUserAndRole();
5. 添加RoleMapper接口使用注解配置Mapper
因为要通过roleid在role表中查询角色,所以要添加RoleMapper接口并添加方法
public interface RoleMapper {
@Select("select * from role r,user_role ur where r.id=ur.roleid and ur.userid=#{uid}")
List<Role> findByUid(int uid);
}
UserMapper 接口中添加注解
//多对多查询
@Select("select * from user")
@Results({
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(column = "id",property = "roleList",
javaType = List.class,
//多对多的查询用many
many = @Many(select = "com.xiafanjun.mapper.RoleMapper.findByUid"))
})
List<User> findAllUserAndRole();
6. 测试结果
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void findAllUserAndRole(){
List<User> allUserAndRole = userMapper.findAllUserAndRole();
for(User user:allUserAndRole){
System.out.println(user);
}
}