<%
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/questionaire", "root", "root");
Statement st=con.createStatement();
ResultSet rs=st.executeQuery("Select * from question");
List arrlist = new ArrayList();
while(rs.next()){
String xa =rs.getString("display");
if(xa.equals("1")){
arrlist.add(rs.getString("q"));
}
}
Collections.shuffle(arrlist); %>
<%for(int i=0;i<5;i++){
String str = (String) arrlist.get(i);%>
<%=str%> //1
<%st.executeUpdate("update question set display='0' where id=?");%> //comment 2
<br>
<%}%>
This is my code.I have some questions which are displayed,then I shuffle them and randomly select 5 questions.The 5 randomly selected questions need to be given display='0' as can be seen in comment 2.How do I do it.I need to pass the id that str has to the database.Could anyone help?
1.) When selecting your questions you should not only "remember" the question-text but also the id. Why not create a new "Question"-class that can keep both values and possibly some more information(correct answer etc.).
public class Question {
private int id;
private String questionText;
private String answer;
private boolean display=false;
public Question(int id,String questionText,String answer) {
this.id = id;
this.questionText = questionText;
this.answer= answer;
}
public int getId() {
return id;
}
public String getQuestionText() {
return questionText;
}
public String getAnswer() {
return answer;
}
public boolean getDisplay() {
return display;
}
public void setDisplay(boolean display) {
this.display = display;
}
}
For each entry in your result-set create a new Question-object and add it to your question-list.
2.) You can't use the =?-syntax with a plain jdbc-Statement-object. You will have to use PreparedStatement for this, then you can set your query-parameters via the setXXX()-methods:
PreparedStatement stmt = conn.prepareStatement("update question set display='0' where id=?");
stmt.setInt(1, question.getId());
stmt.executeUpdate();
3.) When multiple users access your application I'm pretty sure you will get in trouble keeping your "display-state" in the database. Instead use the display-property of the Question-object (see above).
Related
I want to get the value of a MySQL variable (example: max_allowed_packet) via jdbcTemplate. is this possible? if so, how ?
In SQL, I can do SHOW VARIABLES LIKE 'max_allowed_packet'; but how to do this via JDBCTemplate ?
Here is a solution
public List<Variable> findAllVariables() {
List<Variable> result = jdbcTemplate.query("SHOW GLOBAL VARIABLES", new VariableRowMapper());
//about 630 variables
return result;
}
Variable class:
public class Variable {
private String name;
private String value;
//getters and setters
}
VariableRowMapper class:
public class VariableRowMapper implements RowMapper<Variable> {
#Override
public Variable mapRow(ResultSet resultSet, int rowNum) throws SQLException {
String name = resultSet.getString("Variable_Name");
String value = resultSet.getString("Value");
return new Variable(name, value);
}
}
hope it helps.
I was particularly interested in getting the max_allowed_packet variable from the database. This below snippet does the trick.
private int fetchMaxAllowedPacketsFromDB(JdbcTemplate jdbcTemplate) {
final String sql = "SELECT ##GLOBAL.max_allowed_packet";
Integer maxAllowedPacketsFromDB = jdbcTemplate.queryForObject(sql, Integer.class);
log.info("##GLOBAL.max_allowed_packet : {}", maxAllowedPacketsFromDB);
return maxAllowedPacketsFromDB;
}
You can look at #Ali4j 's answer for a more generic/multi-variable requirement.
Or, You can refactor the snippet above to pass in a variable as argument, if you don't need the extra work of RowMappers
Hai I have to add details from one table to another which should be within to dates. These dates are read from text boxes.
But i'm getting Error:
"An exception of type 'MySql.Data.MySqlClient.MySqlException' occurred in MySql.Data.dll but was not handled in user code
Additional information: Incorrect datetime value: '11/25/2015 12:00:00 AM' for column 'debissuedate' at row 1"
The first table is t_bondridapp with fields : id,cancode,canname,debissuedate...etc
And I have to copy from this table to new one named as bondlocal with fields :
bondid,cancode,canname,bonddate.
I've used the code
public class DBConnection
{
private DBConnection()
{
}
private string dbname = string.Empty;
public string DBName
{
get { return dbname;}
set { dbname = value;}
}
public string Password { get; set; }
private MySqlConnection mycon = null;
public MySqlConnection Connection
{
get { return mycon; }
}
private static DBConnection _instance = null;
public static DBConnection Instance()
{
if(_instance==null)
_instance=new DBConnection();
return _instance;
}
public bool IsConnect()
{
bool result = true;
if(mycon==null)
{
if (String.IsNullOrEmpty(dbname))
result = false;
string constr = string.Format("server=localhost;user id=root;password=mysql;database=pnys;",dbname);
mycon = new MySqlConnection(constr);
mycon.Open();
result = true;
}
return result;
}
public void Close()
{
mycon.Close();
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click1(object sender, EventArgs e)
{
MySqlDateTime fdate =new MySqlDateTime(DateTime.Parse(TextBox3.Text));
MySqlDateTime sdate = new MySqlDateTime(DateTime.Parse(TextBox4.Text));
var dbCon = DBConnection.Instance();
dbCon.DBName = "pnys";
if (dbCon.IsConnect())
{
string query = "INSERT INTO bondlocal (cancode,canname,bonddate) SELECT t_bondridapp.cancode,t_bondridapp.canname,t_bondridapp.debissuedate FROM t_bondridapp WHERE debissuedate>='" + fdate + "'AND debissuedate<='" + sdate + "'";
MySqlCommand cmd = new MySqlCommand(query, dbCon.Connection);
cmd.ExecuteNonQuery();
}
Server.Transfer("ReportBonds.aspx");
}
Pls Help Me...
Basically, the problem is how you're passing parameters into the database. You shouldn't need to create a MySqlDateTime yourself - just use parameterized SQL and it should be fine:
// TODO: Use a date/time control instead of parsing text to start with
DateTime fdate = DateTime.Parse(TextBox3.Text);
DateTime sdate = DateTime.Parse(TextBox4.Text);
string query = #"INSERT INTO bondlocal (cancode,canname,bonddate)
SELECT t_bondridapp.cancode,t_bondridapp.canname,t_bondridapp.debissuedate
FROM t_bondridapp
WHERE debissuedate >= #fdate AND debissuedate <= #sdate";
using (var command = new MySqlCommand(query, dbCon))
{
command.Parameters.Add("#fdate", MySqlDbType.Datetime).Value = fdate;
command.Parameters.Add("#sdate", MySqlDbType.Datetime).Value = sdate;
command.ExecuteNonQuery();
}
Basically, you should never specific values within SQL by just using string concatenation. Parameterized SQL prevents SQL injection attacks and conversion issues, and improves code readability.
(As an aside, I would urge you to ditch your current connection sharing, and instead always create and open a new MySqlDbConnection and dispose of it at the end of your operation - rely on the connection pool to make it efficient.)
I'm currently looking to store approximately 3.5 million photo's from approximately 100/200k users. I'm only using a mysql database on aws. My question is in regards to the most efficient way to store the photo reference. I'm only aware of two ways and I'm looking for an expert opinion.
Choice A
A user table with a photo_url column, in that column I would build a comma separated list of photo's that both maintain the name and sort order. The business logic would handle extracting the path from the photo name and append photo size. The downside is the processing expense.
Database example
"0ea102, e435b9, etc"
Business logic would build the following urls from photo name
/0e/a1/02.jpg
/0e/a1/02_thumb.jpg
/e4/35/b9.jpg
/e4/35/b9_thumb.jpg
Choice B - Relational Table joined on user table with the following fields. I'm just concerned I may have potential database performance issues.
pk
user_id
photo_url_800
photo_url_150
photo_url_45
order
Does anybody have any suggestions on the better solution?
The best and most common answer would be: choice B - Relational Table joined on user table with the following fields.
id
order
user_id
desc
photo_url_800
photo_url_150
photo_url_45
date_uploaded
Or a hybrid, wherein, you store the file names individually and add the photo directory with your business logic layer.
My analysis, your first option is a bad practice. Comma separated fields are not advisable for database. It would be difficult for you to update these fields and add description on it.
Regarding the table optimization, you might want to see these articles:
Optimizing MyISAM Queries
Optimizing InnoDB Queries
Here is an example of my final solution using the hibernate ORM, Christian Mark, and my hybrid solution.
#Entity
public class Photo extends StatefulEntity {
private static final String FILE_EXTENSION_JPEG = ".jpg";
private static final String ROOT_PHOTO_URL = "/photo/";
private static final String PHOTO_SIZE_800 = "_800";
private static final String PHOTO_SIZE_150 = "_150";
private static final String PHOTO_SIZE_100 = "_100";
private static final String PHOTO_SIZE_50 = "_50";
#ManyToOne
#JoinColumn(name = "profile_id", nullable = false)
private Profile profile;
//Example "a1d2b0" which will later get parsed into "/photo/a1/d2/b0_size.jpg"
//using the generatePhotoUrl business logic below.
#Column(nullable = false, length = 6)
private String fileName;
private boolean temp;
#Column(nullable = false)
private int orderBy;
#Temporal(TemporalType.TIMESTAMP)
private Date dateUploaded;
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Date getDateUploaded() {
return dateUploaded;
}
public void setDateUploaded(Date dateUploaded) {
this.dateUploaded = dateUploaded;
}
public boolean isTemp() {
return temp;
}
public void setTemp(boolean temp) {
this.temp = temp;
}
public int getOrderBy() {
return orderBy;
}
public void setOrderBy(int orderBy) {
this.orderBy = orderBy;
}
public String getPhotoSize800() {
return generatePhotoURL(PHOTO_SIZE_800);
}
public String getPhotoSize150() {
return generatePhotoURL(PHOTO_SIZE_150);
}
public String getPhotoSize100() {
return generatePhotoURL(PHOTO_SIZE_100);
}
public String getPhotoSize50() {
return generatePhotoURL(PHOTO_SIZE_50);
}
private String generatePhotoURL(String photoSize) {
String firstDir = getFileName().substring(0, 2);
String secondDir = getFileName().substring(2, 4);
String photoName = getFileName().substring(4, 6);
StringBuilder sb = new StringBuilder();
sb.append(ROOT_PHOTO_URL);
sb.append("/");
sb.append(firstDir);
sb.append("/");
sb.append(secondDir);
sb.append("/");
sb.append(photoName);
sb.append(photoSize);
sb.append(FILE_EXTENSION_JPEG);
return sb.toString();
}
}
I have a problem here where i cannot call stored procedure in DNN.I am using DNN 7[lastest].I tried using NamePrefix + "reg_user" but it appear not to call the procedure that I want.Below is what I tried but comes to the same result.
SqlDataProvider.cs[DAL]
public override void AddUser(int ModuleId,string User_name,string User_password,string User_email {
SqlHelper.ExecuteNonQuery(ConnectionString,GetFullyQualifiedName("reg_user"),ModuleId,User_name,User_password,User_email);
}
FeatureController.cs[BL]
Public void AddUser(Register_user reg){
if(reg._User_name.Trim() != "")
{
DataProvider.Instance().AddUser(reg.ModuleId,reg._User_name,reg.User_password,_User_email);
}
}
Register_user.cs[Entity]
public class Register_user
{
public int _ModuleId{ get; set; }
public string _User_name{ get; set; }
public string _User_password{ get; set; }
public string _User_email{ get; set; }
}
view.ascx.cs[UI]
protected void btnregister_Click(object sender, EventArgs e)
{
try
{
FeatureController cntrl = new FeatureController();
Register_user reg = new Register_user()
{
_ModuleId=ModuleId,
_User_name = txtusername.Text,
_User_email = txtemail.Text,
_User_password = txtpassword.Text
};
cntrl.AddUser(reg);
}
catch (Exception ee)
{
lblresult.Text = ee.Message.ToString();
}
}
Error: The store procedure 'dbo.DNNModule2_reg_user' doesn't exist.
Any helps are much appriciated!
I am back with solution update for this question that I asked few days ago.
The solution for this is rather simple.Here is what i need to change.And it will call Sql database without any problem.
public override void AddUser(int ModuleId,string User_name,string User_password,string User_email {
SqlHelper.ExecuteNonQuery(ConnectionString,DatabaseOwner + ObjectQualifier + reg_user",ModuleId,User_name,User_password,User_email);
}
Just change from GetFullyQualifiedName to DatabaseOwner + ObjectQualifier.
I am doing this as a part of good community members.So I tend not to left my question unanswered.
Regrads,
I think you have to look at once on your SqlDataProvider.
private const string providerType = "data";
private const string moduleQualifier = "Objectqualifier_";
this is object qualifier string which added with your SP name like
Objectqualifier_SPname.
and you have to Create SP with same way.
Means you have to Write only last part of sp name in
GetFullyQualifiedName("SPname").
Use debugger to check full name of SP.
and then check your original SP name which is in SQL Server.
Will you please provide me your sp name as in your SQL Server and your
*private const string moduleQualifier
I have a problem with Ebean. I have the usual Objects PsecUser, PsecRoles and PsecPermission.
A user can have many Permissions or Roles and a Role can have many Permission.
Here the code (extract):
#Entity
public class PsecPermission {
#Id
#GeneratedValue
private Long id;
#Column(unique=true, nullable=false)
private String name;
#Column(nullable=false)
private String type = PsecBasicPermission.class.getName();
#Column(nullable=false)
private String target;
#Column(nullable=false)
private String actions;
}
#Entity
public class PsecRole {
#Id
#GeneratedValue
private Long id;
#Column(unique=true, nullable=false)
private String name;
#Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;
#ManyToMany(fetch=FetchType.EAGER)
private List<PsecPermission> psecPermissions;
private boolean defaultRole = false;
}
I wrote the following helper-method:
public PsecRole createOrUpdateRole(String name, boolean defaultRole, String... permissions) {
PsecRole result = server.find(PsecRole.class).
where().eq("name", name).findUnique();
if (result == null) {
result = new PsecRole();
result.setName(name);
}
final List<PsecPermission> permissionObjects = server.find(PsecPermission.class).
where().in("name", (Object[])permissions).findList();
result.setPsecPermissions(permissionObjects);
result.setDefaultRole(defaultRole);
final Set <ConstraintViolation <PsecRole>> errors =
Validation.getValidator().validate(result);
if (errors.isEmpty()) {
server.save(result);
server.saveManyToManyAssociations(result, "psecPermissions");
} else {
log.error("Can't save role: " + name +"!");
for (ConstraintViolation <PsecRole> constraintViolation : errors) {
log.error(" " + constraintViolation);
}
}
return result;
}
and try the following test:
#Test
public void testCreateOrUpdateRole() {
String[] permNames = {"Test1", "Test2", "Test3"};
List <PsecPermission> permissions = new ArrayList <PsecPermission>();
for (int i = 0; i < permNames.length; i++) {
helper.createOrUpdatePermission(permNames[i], "target"+ i, "actions" +i);
PsecPermission perm = server.find(PsecPermission.class).where().eq("name", permNames[i]).findUnique();
assertThat(perm.getTarget()).isEqualTo("target" + i);
assertThat(perm.getActions()).isEqualTo("actions" + i);
permissions.add(perm);
}
PsecRole orgRole = helper.createOrUpdateRole(ROLE, false, permNames);
testRole(permNames, orgRole);
PsecRole role = server.find(PsecRole.class).where().eq("name", ROLE).findUnique();
testRole(permNames, role);
}
private void testRole(String[] permNames, PsecRole role) {
assertThat(role).isNotNull();
assertThat(role.getName()).isEqualTo(ROLE);
assertThat(role.isDefaultRole()).isEqualTo(false);
assertThat(role.getPermissions()).hasSize(permNames.length);
}
Which fails if it checks the number of permissions at the readed role. It's always 0.
I looked into the database and found that psec_role_psec_permission is alway empty.
Any idea what's wrong with the code?
You can get a pure Ebean-example from https://github.com/opensource21/ebean-samples/downloads it uses the eclipse-plugin from ebean.
There are two solutions for this problem:
Simply add cascade option at PsceRole
#ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
private List<PsecPermission> psecPermissions;
and remove server.saveManyToManyAssociations(result, "psecPermissions"); you find it in the cascade-solution-branch.
The cleaner solution, because you don't need to define cascase- perhaps you don't want it:
Just don't replace the list, just add your entries to the list. Better is to add new and remove old one. This mean in createOrUpdateRole:
result.getPsecPermissions().addAll(permissionObjects);
instead of
result.setPsecPermissions(permissionObjects);