android对象关系映射框架ormlite学习之多对多(ManyToMany)

前面介绍了ormlite操作单张表以及多表之间的一对多(多对一)的关系(请参考android对象关系映射框架ormlite学习之单表操作android关系映射框架ormlite学习之OneToMany),但是我们还经常会遇到多对多的数据库表关系,在处理多对多的关系表时,ormlite官方给出的解决方案是通过建立第三张关联表来解决的。这里通过这个解决方案来解决我们最后一个关于多对多关系。

我假设的场景是项目(Project)和用户(User),即一个用户参与多个项目,而一个项目又由多个人员进行开发,构成多对多的关系。同样的对于中间重要的方法类注释在代码中。首先同样给出运行效果图:

android对象关系映射框架ormlite学习之多对多(ManyToMany)

android对象关系映射框架ormlite学习之多对多(ManyToMany)

实体用户类User.java

@DatabaseTable(tableName = "tb_user")
public class User {
	//这里用一个常量来设置属性的名字,这样我们在中就可以直接使用该名字
	public final static String ID_FIELD_NAME = "user_id";
	//用户编号
	@DatabaseField(generatedId=true,columnName=ID_FIELD_NAME)
	private int userId;
	//用户名
	@DatabaseField
	private String userName;
	
	public User() {
		//提供无参构造函数,这样查询的时候可以返回查询出来的对象
	}
	public User( int userId,String userName) {
		this.userId = userId;
		this.userName = userName;
	}
	get/set方法
}
实体项目类Project.java

/**
 * 项目类(假设一个用户参与多个项目,一个项目又由多个用户参与负责)
 * @author leox
 *
 */
@DatabaseTable(tableName="tb_project")
public class Project {
	public final static String ID_FIELD_NAME = "project_id";
	//项目编号
	@DatabaseField(generatedId=true,columnName=ID_FIELD_NAME)
	private int projectId;
	//项目名
	@DatabaseField
	private String projectName;
	public Project() {}
	public Project(int projectId, String projectName) {
		this.projectId = projectId;
		this.projectName = projectName;
	}
	get/set方法
}
用户项目关联类

/**
 * 用户项目关联类
 *(用ormlite实现ManyToMany需要在数据库中建立一张关联表)
 * @author leox
 *
 */
@DatabaseTable(tableName="tb_user_project")
public class UserProject {
	public final static String USER_ID_FIELD_NAME = "user_id";
	public final static String PROJECT_ID_FIELD_NAME = "project_id";
	//用户项目编号
	@DatabaseField(generatedId=true)
	private int id;
	//关联用户表
	@DatabaseField(foreign = true,columnName=USER_ID_FIELD_NAME)
	private User user;
	//关联项目表
	@DatabaseField(foreign = true,columnName=PROJECT_ID_FIELD_NAME)
	private Project project;
	
	public UserProject(){}

	public UserProject(int id, User user, Project project) {
		this.id = id;
		this.user = user;
		this.project = project;
	}

	get/set方法
	
}
SQLLiteHelper类:

public class DatabaseHelper extends OrmLiteSqliteOpenHelper{
    // 数据库名称  
	private static final String DATABASE_NAME = "helloAndroid.db"; 
    // 数据库version  
	private static final int DATABASE_VERSION = 1;
	
	private PreparedQuery<Project> projectsForUserQuery = null;
	private PreparedQuery<User> usersForProjectQuery = null;
	
	/**
	 * 包含两个泛型:
	 * 第一个泛型表DAO操作的类
	 * 第二个表示操作类的主键类型
	 */
	private RuntimeExceptionDao<User, Integer> simpleRuntimeUserDao = null;
	private RuntimeExceptionDao<Project, Integer> simpleRuntimeProjectDao = null;
	private RuntimeExceptionDao<UserProject, Integer> simpleRuntimeUserProjectDao = null;
    
	public DatabaseHelper(Context context) {
		super(context, DATABASE_NAME, null, DATABASE_VERSION);
	}
	
	@Override
	public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) {
		try {
			Log.i(DatabaseHelper.class.getName(), "onCreate");
			//创建用户、项目、用户项目关联三张表
			TableUtils.createTable(connectionSource, UserProject.class);
			TableUtils.createTable(connectionSource, User.class);
			TableUtils.createTable(connectionSource, Project.class);
		} catch (SQLException e) {
			Log.e(DatabaseHelper.class.getName(), "Can‘t create database", e);
			throw new RuntimeException(e);
		}
		
	}
	/**
	 * 插入一条用户数据
	 */
	public void insert(User user){
		RuntimeExceptionDao<User, Integer> dao = getSimpleDataUserDao();
		//通过实体对象创建在数据库中创建一条数据,成功返回1,说明插入了一条数据
		Log.i("test", "dao = " + dao+"  user= "+user);
		int returnValue = dao.create(user);
		Log.i("test", "插入数据后返回值:"+returnValue);
	}
	/**
	 * 查询所有的用户信息
	 * @return
	 */
	public List<User> findAllUser(){
		RuntimeExceptionDao<User, Integer> dao = getSimpleDataUserDao();
		return dao.queryForAll();
	}
	
	public RuntimeExceptionDao<User, Integer> getSimpleDataUserDao() {
		if (simpleRuntimeUserDao == null) {
			simpleRuntimeUserDao = getRuntimeExceptionDao(User.class);
		}
		Log.i("test", "simpleRuntimeDao ======= "+simpleRuntimeUserDao);
		return simpleRuntimeUserDao;
	}

	/**
	 * 这个方法在你的应用升级以及它有一个更高的版本号时调用。所以需要你调整各种数据来适应新的版本
	 */
	@Override
	public void onUpgrade(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource, int oldVersion,
			int newVersion) {
		Log.i("test", "更新....");
		try {
			Log.i(DatabaseHelper.class.getName(), "onUpgrade");
			//删掉旧版本的数据
			TableUtils.dropTable(connectionSource, User.class, true);
			TableUtils.dropTable(connectionSource, UserProject.class, true);
			//创建一个新的版本
			onCreate(sqliteDatabase, connectionSource);
		} catch (SQLException e) {
			Log.e(DatabaseHelper.class.getName(), "Can‘t drop databases", e);
			throw new RuntimeException(e);
		}
	}
	
	/***************************************以下为用户项目关联操作******************************************/
	
	
	public RuntimeExceptionDao<UserProject, Integer> getSimpleDataUserProjectDao() {
		if (simpleRuntimeUserProjectDao == null) {
			simpleRuntimeUserProjectDao = getRuntimeExceptionDao(UserProject.class);
		}
		Log.i("test", "simpleRuntimeDaodeptdept ======= "+simpleRuntimeUserProjectDao);
		return simpleRuntimeUserProjectDao;
	}
	
	/**
	 * 插入一条用户项目关联数据
	 */
	public void insertDept(UserProject dept){
		RuntimeExceptionDao<UserProject, Integer> dao = getSimpleDataUserProjectDao();
		//通过实体对象创建在数据库中创建一条数据,成功返回1,说明插入了一条数据
		int returnValue = dao.create(dept);
		Log.i("test", "插入数据后返回值:"+returnValue);
	}
	
	/****************以下为对项目的操作*********************/
	
	public RuntimeExceptionDao<Project, Integer> getSimpleDataProjectDao() {
		if (simpleRuntimeProjectDao == null) {
			simpleRuntimeProjectDao = getRuntimeExceptionDao(Project.class);
		}
		Log.i("test", "simpleRuntimeDaodeptdept ======= "+simpleRuntimeProjectDao);
		return simpleRuntimeProjectDao;
	}
	
	public Project findByDeptId(int projectId){
		RuntimeExceptionDao<Project, Integer> dao = getSimpleDataProjectDao();
		return dao.queryForId(projectId);
	}
	
	/**
	 * 插入一条项目数据
	 */
	public void insertProject(Project project){
		RuntimeExceptionDao<Project, Integer> dao = getSimpleDataProjectDao();
		//通过实体对象创建在数据库中创建一条数据,成功返回1,说明插入了一条数据
		int returnValue = dao.create(project);
		Log.i("test", "插入数据后返回值:"+returnValue);
	}
	
	public List<Project> lookupProjectsForUser(User user) throws SQLException {
		RuntimeExceptionDao<Project, Integer> dao = getSimpleDataProjectDao();
		if (projectsForUserQuery == null) {
			projectsForUserQuery = makePostsForUserQuery();
		}
		projectsForUserQuery.setArgumentHolderValue(0, user);
		return dao.query(projectsForUserQuery);
	}
	
	/**
	 * 查询某个用户所对应的项目
	 */
	private PreparedQuery<Project> makePostsForUserQuery() throws SQLException {
		RuntimeExceptionDao<UserProject, Integer> userProjectDao = getSimpleDataUserProjectDao();
		RuntimeExceptionDao<Project, Integer> projectDao = getSimpleDataProjectDao();
		//创建一个内关联查询用户项目表
		QueryBuilder<UserProject, Integer> userProject = userProjectDao.queryBuilder();
		//查询关联表tb_user_project时返回“project_id”如果没有该语句,即返回该表所有字段,相当于“select * from 表名”
		//拼成sql语句:select project_id from tb_user_project
		userProject.selectColumns(UserProject.PROJECT_ID_FIELD_NAME);
		//这相当于一个可变的参数,相当于SQL语句中的“?”,这个参数会在后面的操作中指明
		SelectArg userSelectArg = new SelectArg();
		//设置条件语句(where user_id=?)
		userProject.where().eq(UserProject.USER_ID_FIELD_NAME, userSelectArg);
		//创建外部查询项目表
		QueryBuilder<Project, Integer> postQb = projectDao.queryBuilder();
		//设置查询条件(where project_id in());
		postQb.where().in(Project.ID_FIELD_NAME, userProject);
		/**
		 * 这里返回时完整的sql语句为
		 * "SELECT * FROM `tb_project`
		 * 		WHERE `project_id` IN (
		 * 			SELECT `project_id` FROM `tb_user_project` WHERE `user_id` = ? 
		 * 		) "
		 */
		return postQb.prepare();
	}
	public List<User> lookupUsersForProject(Project project) throws SQLException {
		RuntimeExceptionDao<User, Integer> dao = getSimpleDataUserDao();
		if (usersForProjectQuery == null) {
			usersForProjectQuery = makeUsersForProjectQuery();
		}
		usersForProjectQuery.setArgumentHolderValue(0, project);
		return dao.query(usersForProjectQuery);
	}
	/**
	 * 查询某个项目的所有负责人
	 */
	private PreparedQuery<User> makeUsersForProjectQuery() throws SQLException {
		RuntimeExceptionDao<UserProject, Integer> userProjectDao = getSimpleDataUserProjectDao();
		RuntimeExceptionDao<User, Integer> userDao = getSimpleDataUserDao();
		QueryBuilder<UserProject, Integer> userProject = userProjectDao.queryBuilder();
		userProject.selectColumns(UserProject.USER_ID_FIELD_NAME);
		SelectArg userSelectArg = new SelectArg();
		userProject.where().eq(UserProject.PROJECT_ID_FIELD_NAME, userSelectArg);
		QueryBuilder<User, Integer> postQb = userDao.queryBuilder();
		postQb.where().in(User.ID_FIELD_NAME, userProject);
		return postQb.prepare();
	}
}
Activity类:

public class MainActivity extends Activity {

	Button button1;//数据初始化按钮
	Button button2;//显示某人参与的项目
	Button button3;//显示某项目参与的人员
	TextView textView;//用来显示查询到的用户信息
	DatabaseHelper helper = new DatabaseHelper(this);
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		button1 = (Button)this.findViewById(R.id.main_btn_inputinfo);
		button2 = (Button)this.findViewById(R.id.main_project_show);
		button3 = (Button)this.findViewById(R.id.main_user_show);
		textView = (TextView)this.findViewById(R.id.main_show_user);
		//点击注册按钮跳转到注册页面
		button1.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//创建第一个用户
				User user1 = new User();
				user1.setUserName("张三");
				helper.insert(user1);
				//创建第一个项目
				Project project1 = new Project();
				project1.setProjectName("项目一");
				helper.insertProject(project1);
				//将用户一和项目一关联起来
				UserProject up1 = new UserProject();
				up1.setProject(project1);
				up1.setUser(user1);
				helper.insertDept(up1);
				//创建第二个项目
				Project project2 = new Project();
				project2.setProjectName("项目二");
				helper.insertProject(project2);
				//将用户一和项目二关联起来(即用户一参与了项目一和项目二)
				UserProject up2 = new UserProject();
				up2.setProject(project2);
				up2.setUser(user1);
				helper.insertDept(up2);
				
				//创建第二个用户
				User user2 = new User();
				user2.setUserName("李四");
				helper.insert(user2);
				//将用户二和项目二关联起来(即项目二由用户一和用户二共同开发)
				UserProject up3 = new UserProject();
				up3.setProject(project2);
				up3.setUser(user2);
				helper.insertDept(up3);
				
				Toast.makeText(MainActivity.this, "初始化成功!", Toast.LENGTH_LONG);
			}
		});
		//点击显示某个人负责的项目按钮时的操作(将前面添加的用户一所对应的项目显示出来)
		button2.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				List<User> users = helper.findAllUser();
				if(users.size()>0){
					String str = users.get(0).getUserName()+" 参与的项目:";
					try {
						List<Project> proList = helper.lookupProjectsForUser(users.get(0));
						if(proList.size()>0){
							for(Project p:proList){
								//Log.i("test", "项目名:"+p.getProjectName());
								str+=p.getProjectName()+",";
							}
						}
						textView.setText(str);
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		});
		//点击显示某项目负责人按钮时的操作(将项目二的负责人信息显示出来)
				button3.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						Project project = helper.findByDeptId(2);
						if(project!=null){
							String str = project.getProjectName()+" 参与的人员有:";
							try {
								List<User> userList = helper.lookupUsersForProject(project);
								if(userList.size()>0){
									for(User u:userList){
										//Log.i("test", "项目名:"+p.getProjectName());
										str+=u.getUserName()+",";
									}
								}
								textView.setText(str);
							} catch (SQLException e) {
								e.printStackTrace();
							}
						}
					}
				});
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}




android对象关系映射框架ormlite学习之多对多(ManyToMany),布布扣,bubuko.com

android对象关系映射框架ormlite学习之多对多(ManyToMany)

上一篇:Android中SoundPool 类使用利弊


下一篇:iOS开发时,UITextFiled在点击后选择文本